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