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