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 <string.h>
     12 
     13 #include <list>
     14 
     15 #include "testing/gmock/include/gmock/gmock.h"
     16 #include "testing/gtest/include/gtest/gtest.h"
     17 #include "webrtc/modules/rtp_rtcp/interface/fec_receiver.h"
     18 #include "webrtc/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h"
     19 #include "webrtc/modules/rtp_rtcp/source/fec_test_helper.h"
     20 #include "webrtc/modules/rtp_rtcp/source/forward_error_correction.h"
     21 
     22 using ::testing::_;
     23 using ::testing::Args;
     24 using ::testing::ElementsAreArray;
     25 using ::testing::Return;
     26 
     27 namespace webrtc {
     28 
     29 class ReceiverFecTest : public ::testing::Test {
     30  protected:
     31   virtual void SetUp() {
     32     fec_ = new ForwardErrorCorrection();
     33     receiver_fec_ = FecReceiver::Create(&rtp_data_callback_);
     34     generator_ = new FrameGenerator();
     35   }
     36 
     37   virtual void TearDown() {
     38     delete fec_;
     39     delete receiver_fec_;
     40     delete generator_;
     41   }
     42 
     43   void GenerateFEC(std::list<Packet*>* media_packets,
     44                    std::list<Packet*>* fec_packets,
     45                    unsigned int num_fec_packets) {
     46     uint8_t protection_factor = num_fec_packets * 255 / media_packets->size();
     47     EXPECT_EQ(0, fec_->GenerateFEC(*media_packets, protection_factor,
     48                                    0, false, kFecMaskBursty, fec_packets));
     49     ASSERT_EQ(num_fec_packets, fec_packets->size());
     50   }
     51 
     52   void GenerateFrame(int num_media_packets, int frame_offset,
     53                      std::list<RtpPacket*>* media_rtp_packets,
     54                      std::list<Packet*>* media_packets) {
     55     generator_->NewFrame(num_media_packets);
     56     for (int i = 0; i < num_media_packets; ++i) {
     57       media_rtp_packets->push_back(
     58           generator_->NextPacket(frame_offset + i, kRtpHeaderSize + 10));
     59       media_packets->push_back(media_rtp_packets->back());
     60     }
     61   }
     62 
     63   void VerifyReconstructedMediaPacket(const RtpPacket* packet, int times) {
     64     // Verify that the content of the reconstructed packet is equal to the
     65     // content of |packet|, and that the same content is received |times| number
     66     // of times in a row.
     67     EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, packet->length))
     68         .With(Args<0, 1>(ElementsAreArray(packet->data,
     69                                           packet->length)))
     70         .Times(times).WillRepeatedly(Return(true));
     71   }
     72 
     73   void BuildAndAddRedMediaPacket(RtpPacket* packet) {
     74     RtpPacket* red_packet = generator_->BuildMediaRedPacket(packet);
     75     EXPECT_EQ(0, receiver_fec_->AddReceivedRedPacket(
     76                      red_packet->header.header, red_packet->data,
     77                      red_packet->length, kFecPayloadType));
     78     delete red_packet;
     79   }
     80 
     81   void BuildAndAddRedFecPacket(Packet* packet) {
     82     RtpPacket* red_packet = generator_->BuildFecRedPacket(packet);
     83     EXPECT_EQ(0, receiver_fec_->AddReceivedRedPacket(
     84                      red_packet->header.header, red_packet->data,
     85                      red_packet->length, kFecPayloadType));
     86     delete red_packet;
     87   }
     88 
     89   ForwardErrorCorrection* fec_;
     90   MockRtpData rtp_data_callback_;
     91   FecReceiver* receiver_fec_;
     92   FrameGenerator* generator_;
     93 };
     94 
     95 void DeletePackets(std::list<Packet*>* packets) {
     96   while (!packets->empty()) {
     97     delete packets->front();
     98     packets->pop_front();
     99   }
    100 }
    101 
    102 TEST_F(ReceiverFecTest, TwoMediaOneFec) {
    103   const unsigned int kNumFecPackets = 1u;
    104   std::list<RtpPacket*> media_rtp_packets;
    105   std::list<Packet*> media_packets;
    106   GenerateFrame(2, 0, &media_rtp_packets, &media_packets);
    107   std::list<Packet*> fec_packets;
    108   GenerateFEC(&media_packets, &fec_packets, kNumFecPackets);
    109 
    110   // Recovery
    111   std::list<RtpPacket*>::iterator it = media_rtp_packets.begin();
    112   std::list<RtpPacket*>::iterator media_it = media_rtp_packets.begin();
    113   BuildAndAddRedMediaPacket(*media_it);
    114   VerifyReconstructedMediaPacket(*it, 1);
    115   EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
    116   // Drop one media packet.
    117   std::list<Packet*>::iterator fec_it = fec_packets.begin();
    118   BuildAndAddRedFecPacket(*fec_it);
    119   ++it;
    120   VerifyReconstructedMediaPacket(*it, 1);
    121   EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
    122 
    123   DeletePackets(&media_packets);
    124 }
    125 
    126 TEST_F(ReceiverFecTest, TwoMediaTwoFec) {
    127   const unsigned int kNumFecPackets = 2u;
    128   std::list<RtpPacket*> media_rtp_packets;
    129   std::list<Packet*> media_packets;
    130   GenerateFrame(2, 0, &media_rtp_packets, &media_packets);
    131   std::list<Packet*> fec_packets;
    132   GenerateFEC(&media_packets, &fec_packets, kNumFecPackets);
    133 
    134   // Recovery
    135   // Drop both media packets.
    136   std::list<RtpPacket*>::iterator it = media_rtp_packets.begin();
    137   std::list<Packet*>::iterator fec_it = fec_packets.begin();
    138   BuildAndAddRedFecPacket(*fec_it);
    139   VerifyReconstructedMediaPacket(*it, 1);
    140   EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
    141   ++fec_it;
    142   BuildAndAddRedFecPacket(*fec_it);
    143   ++it;
    144   VerifyReconstructedMediaPacket(*it, 1);
    145   EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
    146 
    147   DeletePackets(&media_packets);
    148 }
    149 
    150 TEST_F(ReceiverFecTest, TwoFramesOneFec) {
    151   const unsigned int kNumFecPackets = 1u;
    152   std::list<RtpPacket*> media_rtp_packets;
    153   std::list<Packet*> media_packets;
    154   GenerateFrame(1, 0, &media_rtp_packets, &media_packets);
    155   GenerateFrame(1, 1, &media_rtp_packets, &media_packets);
    156   std::list<Packet*> fec_packets;
    157   GenerateFEC(&media_packets, &fec_packets, kNumFecPackets);
    158 
    159   // Recovery
    160   std::list<RtpPacket*>::iterator it = media_rtp_packets.begin();
    161   BuildAndAddRedMediaPacket(media_rtp_packets.front());
    162   VerifyReconstructedMediaPacket(*it, 1);
    163   EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
    164   // Drop one media packet.
    165   BuildAndAddRedFecPacket(fec_packets.front());
    166   ++it;
    167   VerifyReconstructedMediaPacket(*it, 1);
    168   EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
    169 
    170   DeletePackets(&media_packets);
    171 }
    172 
    173 TEST_F(ReceiverFecTest, OneCompleteOneUnrecoverableFrame) {
    174   const unsigned int kNumFecPackets = 1u;
    175   std::list<RtpPacket*> media_rtp_packets;
    176   std::list<Packet*> media_packets;
    177   GenerateFrame(1, 0, &media_rtp_packets, &media_packets);
    178   GenerateFrame(2, 1, &media_rtp_packets, &media_packets);
    179 
    180   std::list<Packet*> fec_packets;
    181   GenerateFEC(&media_packets, &fec_packets, kNumFecPackets);
    182 
    183   // Recovery
    184   std::list<RtpPacket*>::iterator it = media_rtp_packets.begin();
    185   BuildAndAddRedMediaPacket(*it);  // First frame: one packet.
    186   VerifyReconstructedMediaPacket(*it, 1);
    187   EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
    188   ++it;
    189   BuildAndAddRedMediaPacket(*it);  // First packet of second frame.
    190   VerifyReconstructedMediaPacket(*it, 1);
    191   EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
    192 
    193   DeletePackets(&media_packets);
    194 }
    195 
    196 TEST_F(ReceiverFecTest, MaxFramesOneFec) {
    197   const unsigned int kNumFecPackets = 1u;
    198   const unsigned int kNumMediaPackets = 48u;
    199   std::list<RtpPacket*> media_rtp_packets;
    200   std::list<Packet*> media_packets;
    201   for (unsigned int i = 0; i < kNumMediaPackets; ++i) {
    202     GenerateFrame(1, i, &media_rtp_packets, &media_packets);
    203   }
    204   std::list<Packet*> fec_packets;
    205   GenerateFEC(&media_packets, &fec_packets, kNumFecPackets);
    206 
    207   // Recovery
    208   std::list<RtpPacket*>::iterator it = media_rtp_packets.begin();
    209   ++it;  // Drop first packet.
    210   for (; it != media_rtp_packets.end(); ++it) {
    211     BuildAndAddRedMediaPacket(*it);
    212     VerifyReconstructedMediaPacket(*it, 1);
    213     EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
    214   }
    215   BuildAndAddRedFecPacket(fec_packets.front());
    216   it = media_rtp_packets.begin();
    217   VerifyReconstructedMediaPacket(*it, 1);
    218   EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
    219 
    220   DeletePackets(&media_packets);
    221 }
    222 
    223 TEST_F(ReceiverFecTest, TooManyFrames) {
    224   const unsigned int kNumFecPackets = 1u;
    225   const unsigned int kNumMediaPackets = 49u;
    226   std::list<RtpPacket*> media_rtp_packets;
    227   std::list<Packet*> media_packets;
    228   for (unsigned int i = 0; i < kNumMediaPackets; ++i) {
    229     GenerateFrame(1, i, &media_rtp_packets, &media_packets);
    230   }
    231   std::list<Packet*> fec_packets;
    232   EXPECT_EQ(-1, fec_->GenerateFEC(media_packets,
    233                                   kNumFecPackets * 255 / kNumMediaPackets, 0,
    234                                   false, kFecMaskBursty, &fec_packets));
    235 
    236   DeletePackets(&media_packets);
    237 }
    238 
    239 TEST_F(ReceiverFecTest, PacketNotDroppedTooEarly) {
    240   // 1 frame with 2 media packets and one FEC packet. One media packet missing.
    241   // Delay the FEC packet.
    242   Packet* delayed_fec = NULL;
    243   const unsigned int kNumFecPacketsBatch1 = 1u;
    244   const unsigned int kNumMediaPacketsBatch1 = 2u;
    245   std::list<RtpPacket*> media_rtp_packets_batch1;
    246   std::list<Packet*> media_packets_batch1;
    247   GenerateFrame(kNumMediaPacketsBatch1, 0, &media_rtp_packets_batch1,
    248                 &media_packets_batch1);
    249   std::list<Packet*> fec_packets;
    250   GenerateFEC(&media_packets_batch1, &fec_packets, kNumFecPacketsBatch1);
    251 
    252   BuildAndAddRedMediaPacket(media_rtp_packets_batch1.front());
    253   EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _))
    254       .Times(1).WillRepeatedly(Return(true));
    255   EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
    256   delayed_fec = fec_packets.front();
    257 
    258   // Fill the FEC decoder. No packets should be dropped.
    259   const unsigned int kNumMediaPacketsBatch2 = 46u;
    260   std::list<RtpPacket*> media_rtp_packets_batch2;
    261   std::list<Packet*> media_packets_batch2;
    262   for (unsigned int i = 0; i < kNumMediaPacketsBatch2; ++i) {
    263     GenerateFrame(1, i, &media_rtp_packets_batch2, &media_packets_batch2);
    264   }
    265   for (std::list<RtpPacket*>::iterator it = media_rtp_packets_batch2.begin();
    266        it != media_rtp_packets_batch2.end(); ++it) {
    267     BuildAndAddRedMediaPacket(*it);
    268     EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _))
    269         .Times(1).WillRepeatedly(Return(true));
    270     EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
    271   }
    272 
    273   // Add the delayed FEC packet. One packet should be reconstructed.
    274   BuildAndAddRedFecPacket(delayed_fec);
    275   EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _))
    276       .Times(1).WillRepeatedly(Return(true));
    277   EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
    278 
    279   DeletePackets(&media_packets_batch1);
    280   DeletePackets(&media_packets_batch2);
    281 }
    282 
    283 TEST_F(ReceiverFecTest, PacketDroppedWhenTooOld) {
    284   // 1 frame with 2 media packets and one FEC packet. One media packet missing.
    285   // Delay the FEC packet.
    286   Packet* delayed_fec = NULL;
    287   const unsigned int kNumFecPacketsBatch1 = 1u;
    288   const unsigned int kNumMediaPacketsBatch1 = 2u;
    289   std::list<RtpPacket*> media_rtp_packets_batch1;
    290   std::list<Packet*> media_packets_batch1;
    291   GenerateFrame(kNumMediaPacketsBatch1, 0, &media_rtp_packets_batch1,
    292                 &media_packets_batch1);
    293   std::list<Packet*> fec_packets;
    294   GenerateFEC(&media_packets_batch1, &fec_packets, kNumFecPacketsBatch1);
    295 
    296   BuildAndAddRedMediaPacket(media_rtp_packets_batch1.front());
    297   EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _))
    298       .Times(1).WillRepeatedly(Return(true));
    299   EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
    300   delayed_fec = fec_packets.front();
    301 
    302   // Fill the FEC decoder and force the last packet to be dropped.
    303   const unsigned int kNumMediaPacketsBatch2 = 48u;
    304   std::list<RtpPacket*> media_rtp_packets_batch2;
    305   std::list<Packet*> media_packets_batch2;
    306   for (unsigned int i = 0; i < kNumMediaPacketsBatch2; ++i) {
    307     GenerateFrame(1, i, &media_rtp_packets_batch2, &media_packets_batch2);
    308   }
    309   for (std::list<RtpPacket*>::iterator it = media_rtp_packets_batch2.begin();
    310        it != media_rtp_packets_batch2.end(); ++it) {
    311     BuildAndAddRedMediaPacket(*it);
    312     EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _))
    313         .Times(1).WillRepeatedly(Return(true));
    314     EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
    315   }
    316 
    317   // Add the delayed FEC packet. No packet should be reconstructed since the
    318   // first media packet of that frame has been dropped due to being too old.
    319   BuildAndAddRedFecPacket(delayed_fec);
    320   EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _))
    321       .Times(0);
    322   EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
    323 
    324   DeletePackets(&media_packets_batch1);
    325   DeletePackets(&media_packets_batch2);
    326 }
    327 
    328 TEST_F(ReceiverFecTest, OldFecPacketDropped) {
    329   // 49 frames with 2 media packets and one FEC packet. All media packets
    330   // missing.
    331   const unsigned int kNumMediaPackets = 49 * 2;
    332   std::list<RtpPacket*> media_rtp_packets;
    333   std::list<Packet*> media_packets;
    334   for (unsigned int i = 0; i < kNumMediaPackets / 2; ++i) {
    335     std::list<RtpPacket*> frame_media_rtp_packets;
    336     std::list<Packet*> frame_media_packets;
    337     std::list<Packet*> fec_packets;
    338     GenerateFrame(2, 0, &frame_media_rtp_packets, &frame_media_packets);
    339     GenerateFEC(&frame_media_packets, &fec_packets, 1);
    340     for (std::list<Packet*>::iterator it = fec_packets.begin();
    341          it != fec_packets.end(); ++it) {
    342       // Only FEC packets inserted. No packets recoverable at this time.
    343       BuildAndAddRedFecPacket(*it);
    344       EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _))
    345           .Times(0);
    346       EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
    347     }
    348     media_packets.insert(media_packets.end(), frame_media_packets.begin(),
    349                          frame_media_packets.end());
    350     media_rtp_packets.insert(media_rtp_packets.end(),
    351                              frame_media_rtp_packets.begin(),
    352                              frame_media_rtp_packets.end());
    353   }
    354   // Insert the oldest media packet. The corresponding FEC packet is too old
    355   // and should've been dropped. Only the media packet we inserted will be
    356   // returned.
    357   BuildAndAddRedMediaPacket(media_rtp_packets.front());
    358   EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _))
    359       .Times(1).WillRepeatedly(Return(true));
    360   EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
    361 
    362   DeletePackets(&media_packets);
    363 }
    364 
    365 }  // namespace webrtc
    366