Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(278)

Side by Side Diff: webrtc/modules/rtp_rtcp/source/rtp_fec_unittest.cc

Issue 2918333002: Reland of Only compare sequence numbers from the same SSRC in ForwardErrorCorrection. (Closed)
Patch Set: Let ForwardErrorCorrection be aware of its SSRCs. Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 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 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
101 ReceivedPackets(media_packets_, media_loss_mask, !kFecPacket); 101 ReceivedPackets(media_packets_, media_loss_mask, !kFecPacket);
102 ReceivedPackets(generated_fec_packets_, fec_loss_mask, kFecPacket); 102 ReceivedPackets(generated_fec_packets_, fec_loss_mask, kFecPacket);
103 } 103 }
104 104
105 template <typename ForwardErrorCorrectionType> 105 template <typename ForwardErrorCorrectionType>
106 template <typename PacketListType> 106 template <typename PacketListType>
107 void RtpFecTest<ForwardErrorCorrectionType>::ReceivedPackets( 107 void RtpFecTest<ForwardErrorCorrectionType>::ReceivedPackets(
108 const PacketListType& packet_list, 108 const PacketListType& packet_list,
109 int* loss_mask, 109 int* loss_mask,
110 bool is_fec) { 110 bool is_fec) {
111 uint16_t fec_seq_num = media_packet_generator_.GetFecSeqNum(); 111 uint16_t fec_seq_num = ForwardErrorCorrectionType::GetFirstFecSeqNum(
112 media_packet_generator_.GetNextSeqNum());
112 int packet_idx = 0; 113 int packet_idx = 0;
113 114
114 for (const auto& packet : packet_list) { 115 for (const auto& packet : packet_list) {
115 if (loss_mask[packet_idx] == 0) { 116 if (loss_mask[packet_idx] == 0) {
116 std::unique_ptr<ForwardErrorCorrection::ReceivedPacket> received_packet( 117 std::unique_ptr<ForwardErrorCorrection::ReceivedPacket> received_packet(
117 new ForwardErrorCorrection::ReceivedPacket()); 118 new ForwardErrorCorrection::ReceivedPacket());
118 received_packet->pkt = new ForwardErrorCorrection::Packet(); 119 received_packet->pkt = new ForwardErrorCorrection::Packet();
119 received_packet->pkt->length = packet->length; 120 received_packet->pkt->length = packet->length;
120 memcpy(received_packet->pkt->data, packet->data, packet->length); 121 memcpy(received_packet->pkt->data, packet->data, packet->length);
121 received_packet->is_fec = is_fec; 122 received_packet->is_fec = is_fec;
122 if (!is_fec) { 123 if (!is_fec) {
123 // For media packets, the sequence number and marker bit is 124 received_packet->ssrc = kMediaSsrc;
124 // obtained from RTP header. These were set in ConstructMediaPackets(). 125 // For media packets, the sequence number is obtained from the
126 // RTP header as written by MediaPacketGenerator::ConstructMediaPackets.
125 received_packet->seq_num = 127 received_packet->seq_num =
126 ByteReader<uint16_t>::ReadBigEndian(&packet->data[2]); 128 ByteReader<uint16_t>::ReadBigEndian(&packet->data[2]);
127 } else { 129 } else {
128 // The sequence number, marker bit, and ssrc number are defined in the 130 received_packet->ssrc = ForwardErrorCorrectionType::kFecSsrc;
129 // RTP header of the FEC packet, which is not constructed in this test. 131 // For FEC packets, we simulate the sequence numbers differently
130 // So we set these values below based on the values generated in 132 // depending on if ULPFEC or FlexFEC is used. See the definition of
131 // ConstructMediaPackets(). 133 // ForwardErrorCorrectionType::GetFirstFecSeqNum.
132 received_packet->seq_num = fec_seq_num; 134 received_packet->seq_num = fec_seq_num;
133 // The ssrc value for FEC packets is set to the one used for the
134 // media packets in ConstructMediaPackets().
135 received_packet->ssrc = kMediaSsrc;
136 } 135 }
137 received_packets_.push_back(std::move(received_packet)); 136 received_packets_.push_back(std::move(received_packet));
138 } 137 }
139 packet_idx++; 138 packet_idx++;
140 // Sequence number of FEC packets are defined as increment by 1 from 139 // Sequence number of FEC packets are defined as increment by 1 from
141 // last media packet in frame. 140 // last media packet in frame.
142 if (is_fec) 141 if (is_fec)
143 fec_seq_num++; 142 fec_seq_num++;
144 } 143 }
145 } 144 }
(...skipping 24 matching lines...) Expand all
170 recovered_packets_.cbegin(), cmp); 169 recovered_packets_.cbegin(), cmp);
171 } 170 }
172 171
173 // Define gTest typed test to loop over both ULPFEC and FlexFEC. 172 // Define gTest typed test to loop over both ULPFEC and FlexFEC.
174 // Since the tests now are parameterized, we need to access 173 // Since the tests now are parameterized, we need to access
175 // member variables using |this|, thereby enforcing runtime 174 // member variables using |this|, thereby enforcing runtime
176 // resolution. 175 // resolution.
177 176
178 class FlexfecForwardErrorCorrection : public ForwardErrorCorrection { 177 class FlexfecForwardErrorCorrection : public ForwardErrorCorrection {
179 public: 178 public:
179 static const uint32_t kFecSsrc = kFlexfecSsrc;
180
180 FlexfecForwardErrorCorrection() 181 FlexfecForwardErrorCorrection()
181 : ForwardErrorCorrection( 182 : ForwardErrorCorrection(
182 std::unique_ptr<FecHeaderReader>(new FlexfecHeaderReader()), 183 std::unique_ptr<FecHeaderReader>(new FlexfecHeaderReader()),
183 std::unique_ptr<FecHeaderWriter>(new FlexfecHeaderWriter())) {} 184 std::unique_ptr<FecHeaderWriter>(new FlexfecHeaderWriter()),
185 kFecSsrc,
186 kMediaSsrc) {}
187
188 // For FlexFEC we let the FEC packet sequence numbers be independent of
189 // the media packet sequence numbers.
190 static uint16_t GetFirstFecSeqNum(uint16_t next_media_seq_num) {
191 Random random(0xbe110);
192 return random.Rand<uint16_t>();
193 }
184 }; 194 };
185 195
186 class UlpfecForwardErrorCorrection : public ForwardErrorCorrection { 196 class UlpfecForwardErrorCorrection : public ForwardErrorCorrection {
187 public: 197 public:
198 static const uint32_t kFecSsrc = kMediaSsrc;
199
188 UlpfecForwardErrorCorrection() 200 UlpfecForwardErrorCorrection()
189 : ForwardErrorCorrection( 201 : ForwardErrorCorrection(
190 std::unique_ptr<FecHeaderReader>(new UlpfecHeaderReader()), 202 std::unique_ptr<FecHeaderReader>(new UlpfecHeaderReader()),
191 std::unique_ptr<FecHeaderWriter>(new UlpfecHeaderWriter())) {} 203 std::unique_ptr<FecHeaderWriter>(new UlpfecHeaderWriter()),
204 kFecSsrc,
205 kMediaSsrc) {}
206
207 // For ULPFEC we assume that the FEC packets are subsequent to the media
208 // packets in terms of sequence number.
209 static uint16_t GetFirstFecSeqNum(uint16_t next_media_seq_num) {
210 return next_media_seq_num;
211 }
192 }; 212 };
193 213
194 using FecTypes = 214 using FecTypes =
195 Types<FlexfecForwardErrorCorrection, UlpfecForwardErrorCorrection>; 215 Types<FlexfecForwardErrorCorrection, UlpfecForwardErrorCorrection>;
196 TYPED_TEST_CASE(RtpFecTest, FecTypes); 216 TYPED_TEST_CASE(RtpFecTest, FecTypes);
197 217
198 TYPED_TEST(RtpFecTest, FecRecoveryNoLoss) { 218 TYPED_TEST(RtpFecTest, FecRecoveryNoLoss) {
199 constexpr int kNumImportantPackets = 0; 219 constexpr int kNumImportantPackets = 0;
200 constexpr bool kUseUnequalProtection = false; 220 constexpr bool kUseUnequalProtection = false;
201 constexpr int kNumMediaPackets = 4; 221 constexpr int kNumMediaPackets = 4;
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
352 372
353 EXPECT_EQ(0, this->fec_.DecodeFec(&this->received_packets_, 373 EXPECT_EQ(0, this->fec_.DecodeFec(&this->received_packets_,
354 &this->recovered_packets_)); 374 &this->recovered_packets_));
355 375
356 // Expect 3 media packets in recovered list, and complete recovery. 376 // Expect 3 media packets in recovered list, and complete recovery.
357 // Wrap-around won't remove FEC packet, as it follows the wrap. 377 // Wrap-around won't remove FEC packet, as it follows the wrap.
358 EXPECT_EQ(3u, this->recovered_packets_.size()); 378 EXPECT_EQ(3u, this->recovered_packets_.size());
359 EXPECT_TRUE(this->IsRecoveryComplete()); 379 EXPECT_TRUE(this->IsRecoveryComplete());
360 } 380 }
361 381
362 // Sequence number wrap occurs within the FEC packets for the frame. 382 // Sequence number wrap occurs within the ULPFEC packets for the frame.
363 // In this case we will discard FEC packet and full recovery is not expected. 383 // In this case we will discard ULPFEC packet and full recovery is not expected.
364 // Same problem will occur if wrap is within media packets but FEC packet is 384 // Same problem will occur if wrap is within media packets but ULPFEC packet is
365 // received before the media packets. This may be improved if timing information 385 // received before the media packets. This may be improved if timing information
366 // is used to detect old FEC packets. 386 // is used to detect old ULPFEC packets.
367 // TODO(marpan): Update test if wrap-around handling changes in FEC decoding. 387 // TODO(marpan): Update test if wrap-around handling changes in FEC decoding.
368 TYPED_TEST(RtpFecTest, FecRecoveryWithSeqNumGapOneFrameNoRecovery) { 388 using RtpFecTestUlpfecOnly = RtpFecTest<UlpfecForwardErrorCorrection>;
389 TEST_F(RtpFecTestUlpfecOnly, FecRecoveryWithSeqNumGapOneFrameNoRecovery) {
369 constexpr int kNumImportantPackets = 0; 390 constexpr int kNumImportantPackets = 0;
370 constexpr bool kUseUnequalProtection = false; 391 constexpr bool kUseUnequalProtection = false;
371 constexpr uint8_t kProtectionFactor = 200; 392 constexpr uint8_t kProtectionFactor = 200;
372 393
373 // 1 frame: 3 media packets and 2 FEC packets. 394 // 1 frame: 3 media packets and 2 FEC packets.
374 // Sequence number wrap in FEC packets. 395 // Sequence number wrap in FEC packets.
375 // -----Frame 1---- 396 // -----Frame 1----
376 // #65532(media) #65533(media) #65534(media) #65535(FEC) #0(FEC). 397 // #65532(media) #65533(media) #65534(media) #65535(FEC) #0(FEC).
377 this->media_packets_ = 398 this->media_packets_ =
378 this->media_packet_generator_.ConstructMediaPackets(3, 65532); 399 this->media_packet_generator_.ConstructMediaPackets(3, 65532);
(...skipping 12 matching lines...) Expand all
391 this->media_loss_mask_[1] = 1; 412 this->media_loss_mask_[1] = 1;
392 this->media_loss_mask_[2] = 1; 413 this->media_loss_mask_[2] = 1;
393 this->ReceivedPackets(this->media_packets_, this->media_loss_mask_, false); 414 this->ReceivedPackets(this->media_packets_, this->media_loss_mask_, false);
394 this->ReceivedPackets(this->generated_fec_packets_, this->fec_loss_mask_, 415 this->ReceivedPackets(this->generated_fec_packets_, this->fec_loss_mask_,
395 true); 416 true);
396 417
397 EXPECT_EQ(0, this->fec_.DecodeFec(&this->received_packets_, 418 EXPECT_EQ(0, this->fec_.DecodeFec(&this->received_packets_,
398 &this->recovered_packets_)); 419 &this->recovered_packets_));
399 420
400 // The two FEC packets are received and should allow for complete recovery, 421 // The two FEC packets are received and should allow for complete recovery,
401 // but because of the wrap the second FEC packet will be discarded, and only 422 // but because of the wrap the first FEC packet will be discarded, and only
402 // one media packet is recoverable. So exepct 2 media packets on recovered 423 // one media packet is recoverable. So expect 2 media packets on recovered
403 // list and no complete recovery. 424 // list and no complete recovery.
404 EXPECT_EQ(2u, this->recovered_packets_.size()); 425 EXPECT_EQ(2u, this->recovered_packets_.size());
405 EXPECT_TRUE(this->recovered_packets_.size() != this->media_packets_.size()); 426 EXPECT_TRUE(this->recovered_packets_.size() != this->media_packets_.size());
427 EXPECT_FALSE(this->IsRecoveryComplete());
428 }
429
430 // TODO(brandtr): This test mimics the one above, ensuring that the recovery
431 // strategy of FlexFEC matches the recovery strategy of ULPFEC. Since FlexFEC
432 // does not share the sequence number space with the media, however, having a
433 // matching recovery strategy may be suboptimal. Study this further.
434 using RtpFecTestFlexfecOnly = RtpFecTest<FlexfecForwardErrorCorrection>;
435 TEST_F(RtpFecTestFlexfecOnly, FecRecoveryWithSeqNumGapOneFrameNoRecovery) {
436 constexpr int kNumImportantPackets = 0;
437 constexpr bool kUseUnequalProtection = false;
438 constexpr uint8_t kProtectionFactor = 200;
439
440 // 1 frame: 3 media packets and 2 FEC packets.
441 // Sequence number wrap in FEC packets.
442 // -----Frame 1----
443 // #65532(media) #65533(media) #65534(media) #65535(FEC) #0(FEC).
444 this->media_packets_ =
445 this->media_packet_generator_.ConstructMediaPackets(3, 65532);
446
447 EXPECT_EQ(
448 0, this->fec_.EncodeFec(this->media_packets_, kProtectionFactor,
449 kNumImportantPackets, kUseUnequalProtection,
450 kFecMaskBursty, &this->generated_fec_packets_));
451
452 // Expect 2 FEC packets.
453 EXPECT_EQ(2u, this->generated_fec_packets_.size());
454
455 // Overwrite the sequence numbers generated by ConstructMediaPackets,
456 // to make sure that we do have a wrap.
457 auto it = this->generated_fec_packets_.begin();
458 ByteWriter<uint16_t>::WriteBigEndian(&(*it)->data[2], 65535);
459 ++it;
460 ByteWriter<uint16_t>::WriteBigEndian(&(*it)->data[2], 0);
461
462 // Lose the last two media packets (seq# 65533, 65534).
463 memset(this->media_loss_mask_, 0, sizeof(this->media_loss_mask_));
464 memset(this->fec_loss_mask_, 0, sizeof(this->fec_loss_mask_));
465 this->media_loss_mask_[1] = 1;
466 this->media_loss_mask_[2] = 1;
467 this->ReceivedPackets(this->media_packets_, this->media_loss_mask_, false);
468 this->ReceivedPackets(this->generated_fec_packets_, this->fec_loss_mask_,
469 true);
470
471 EXPECT_EQ(0, this->fec_.DecodeFec(&this->received_packets_,
472 &this->recovered_packets_));
473
474 // The two FEC packets are received and should allow for complete recovery,
475 // but because of the wrap the first FEC packet will be discarded, and only
476 // one media packet is recoverable. So expect 2 media packets on recovered
477 // list and no complete recovery.
478 EXPECT_EQ(2u, this->recovered_packets_.size());
479 EXPECT_TRUE(this->recovered_packets_.size() != this->media_packets_.size());
406 EXPECT_FALSE(this->IsRecoveryComplete()); 480 EXPECT_FALSE(this->IsRecoveryComplete());
407 } 481 }
408 482
409 // Verify we can still recover frame if media packets are reordered. 483 // Verify we can still recover frame if media packets are reordered.
410 TYPED_TEST(RtpFecTest, FecRecoveryWithMediaOutOfOrder) { 484 TYPED_TEST(RtpFecTest, FecRecoveryWithMediaOutOfOrder) {
411 constexpr int kNumImportantPackets = 0; 485 constexpr int kNumImportantPackets = 0;
412 constexpr bool kUseUnequalProtection = false; 486 constexpr bool kUseUnequalProtection = false;
413 constexpr uint8_t kProtectionFactor = 20; 487 constexpr uint8_t kProtectionFactor = 20;
414 488
415 // One frame: 3 media packets, 1 FEC packet. 489 // One frame: 3 media packets, 1 FEC packet.
(...skipping 11 matching lines...) Expand all
427 EXPECT_EQ(1u, this->generated_fec_packets_.size()); 501 EXPECT_EQ(1u, this->generated_fec_packets_.size());
428 502
429 // Lose one media packet (seq# 1). 503 // Lose one media packet (seq# 1).
430 memset(this->media_loss_mask_, 0, sizeof(this->media_loss_mask_)); 504 memset(this->media_loss_mask_, 0, sizeof(this->media_loss_mask_));
431 memset(this->fec_loss_mask_, 0, sizeof(this->fec_loss_mask_)); 505 memset(this->fec_loss_mask_, 0, sizeof(this->fec_loss_mask_));
432 this->media_loss_mask_[1] = 1; 506 this->media_loss_mask_[1] = 1;
433 this->NetworkReceivedPackets(this->media_loss_mask_, this->fec_loss_mask_); 507 this->NetworkReceivedPackets(this->media_loss_mask_, this->fec_loss_mask_);
434 508
435 // Reorder received media packets. 509 // Reorder received media packets.
436 auto it0 = this->received_packets_.begin(); 510 auto it0 = this->received_packets_.begin();
437 auto it2 = this->received_packets_.begin(); 511 auto it1 = this->received_packets_.begin();
438 it2++; 512 it1++;
439 std::swap(*it0, *it2); 513 std::swap(*it0, *it1);
440 514
441 EXPECT_EQ(0, this->fec_.DecodeFec(&this->received_packets_, 515 EXPECT_EQ(0, this->fec_.DecodeFec(&this->received_packets_,
442 &this->recovered_packets_)); 516 &this->recovered_packets_));
443 517
444 // Expect 3 media packets in recovered list, and complete recovery. 518 // Expect 3 media packets in recovered list, and complete recovery.
445 EXPECT_EQ(3u, this->recovered_packets_.size()); 519 EXPECT_EQ(3u, this->recovered_packets_.size());
446 EXPECT_TRUE(this->IsRecoveryComplete()); 520 EXPECT_TRUE(this->IsRecoveryComplete());
447 } 521 }
448 522
449 // Verify we can still recover frame if FEC is received before media packets. 523 // Verify we can still recover frame if FEC is received before media packets.
(...skipping 501 matching lines...) Expand 10 before | Expand all | Expand 10 after
951 this->media_loss_mask_[kNumMediaPackets - 1] = 1; 1025 this->media_loss_mask_[kNumMediaPackets - 1] = 1;
952 this->NetworkReceivedPackets(this->media_loss_mask_, this->fec_loss_mask_); 1026 this->NetworkReceivedPackets(this->media_loss_mask_, this->fec_loss_mask_);
953 1027
954 EXPECT_EQ(0, this->fec_.DecodeFec(&this->received_packets_, 1028 EXPECT_EQ(0, this->fec_.DecodeFec(&this->received_packets_,
955 &this->recovered_packets_)); 1029 &this->recovered_packets_));
956 1030
957 // 5 protected packets lost, one FEC packet, cannot get complete recovery. 1031 // 5 protected packets lost, one FEC packet, cannot get complete recovery.
958 EXPECT_FALSE(this->IsRecoveryComplete()); 1032 EXPECT_FALSE(this->IsRecoveryComplete());
959 } 1033 }
960 1034
961 // 'using' directive needed for compiler to be happy.
962 using RtpFecTestWithFlexfec = RtpFecTest<FlexfecForwardErrorCorrection>;
963 TEST_F(RtpFecTestWithFlexfec,
964 FecRecoveryWithLossAndDifferentMediaAndFlexfecSsrcs) {
965 constexpr int kNumImportantPackets = 0;
966 constexpr bool kUseUnequalProtection = false;
967 constexpr int kNumMediaPackets = 4;
968 constexpr uint8_t kProtectionFactor = 60;
969
970 media_packets_ =
971 media_packet_generator_.ConstructMediaPackets(kNumMediaPackets);
972
973 EXPECT_EQ(0, fec_.EncodeFec(media_packets_, kProtectionFactor,
974 kNumImportantPackets, kUseUnequalProtection,
975 kFecMaskBursty, &generated_fec_packets_));
976
977 // Expect 1 FEC packet.
978 EXPECT_EQ(1u, generated_fec_packets_.size());
979
980 // 1 media packet lost
981 memset(media_loss_mask_, 0, sizeof(media_loss_mask_));
982 memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_));
983 media_loss_mask_[3] = 1;
984 NetworkReceivedPackets(media_loss_mask_, fec_loss_mask_);
985
986 // Simulate FlexFEC packet received on different SSRC.
987 auto it = received_packets_.begin();
988 ++it;
989 ++it;
990 ++it; // Now at the FEC packet.
991 (*it)->ssrc = kFlexfecSsrc;
992
993 EXPECT_EQ(0, fec_.DecodeFec(&received_packets_, &recovered_packets_));
994
995 // One packet lost, one FEC packet, expect complete recovery.
996 EXPECT_TRUE(IsRecoveryComplete());
997 }
998
999 } // namespace webrtc 1035 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698