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