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