| OLD | NEW |
| (Empty) |
| 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 #include <memory> | |
| 15 | |
| 16 #include "webrtc/modules/rtp_rtcp/include/fec_receiver.h" | |
| 17 #include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h" | |
| 18 #include "webrtc/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h" | |
| 19 #include "webrtc/modules/rtp_rtcp/source/byte_io.h" | |
| 20 #include "webrtc/modules/rtp_rtcp/source/fec_test_helper.h" | |
| 21 #include "webrtc/modules/rtp_rtcp/source/forward_error_correction.h" | |
| 22 #include "webrtc/test/gmock.h" | |
| 23 #include "webrtc/test/gtest.h" | |
| 24 | |
| 25 namespace webrtc { | |
| 26 | |
| 27 namespace { | |
| 28 using ::testing::_; | |
| 29 using ::testing::Args; | |
| 30 using ::testing::ElementsAreArray; | |
| 31 using ::testing::Return; | |
| 32 | |
| 33 using test::fec::AugmentedPacket; | |
| 34 using Packet = ForwardErrorCorrection::Packet; | |
| 35 using test::fec::UlpfecPacketGenerator; | |
| 36 | |
| 37 constexpr int kFecPayloadType = 96; | |
| 38 constexpr uint32_t kMediaSsrc = 835424; | |
| 39 } // namespace | |
| 40 | |
| 41 class ReceiverFecTest : public ::testing::Test { | |
| 42 protected: | |
| 43 ReceiverFecTest() | |
| 44 : fec_(ForwardErrorCorrection::CreateUlpfec()), | |
| 45 receiver_fec_(FecReceiver::Create(&rtp_data_callback_)), | |
| 46 packet_generator_(kMediaSsrc) {} | |
| 47 | |
| 48 // Generates |num_fec_packets| FEC packets, given |media_packets|. | |
| 49 void EncodeFec(const ForwardErrorCorrection::PacketList& media_packets, | |
| 50 size_t num_fec_packets, | |
| 51 std::list<ForwardErrorCorrection::Packet*>* fec_packets); | |
| 52 | |
| 53 // Generates |num_media_packets| corresponding to a single frame. | |
| 54 void PacketizeFrame(size_t num_media_packets, | |
| 55 size_t frame_offset, | |
| 56 std::list<AugmentedPacket*>* augmented_packets, | |
| 57 ForwardErrorCorrection::PacketList* packets); | |
| 58 | |
| 59 // Build a media packet using |packet_generator_| and add it | |
| 60 // to the receiver. | |
| 61 void BuildAndAddRedMediaPacket(AugmentedPacket* packet); | |
| 62 | |
| 63 // Build a FEC packet using |packet_generator_| and add it | |
| 64 // to the receiver. | |
| 65 void BuildAndAddRedFecPacket(Packet* packet); | |
| 66 | |
| 67 // Ensure that |rtp_data_callback_| will be called correctly | |
| 68 // and that the recovered packet will be identical to the lost packet. | |
| 69 void VerifyReconstructedMediaPacket(const AugmentedPacket& packet, | |
| 70 size_t times); | |
| 71 | |
| 72 void InjectGarbagePacketLength(size_t fec_garbage_offset); | |
| 73 | |
| 74 static void SurvivesMaliciousPacket(const uint8_t* data, | |
| 75 size_t length, | |
| 76 uint8_t ulpfec_payload_type); | |
| 77 | |
| 78 MockRtpData rtp_data_callback_; | |
| 79 std::unique_ptr<ForwardErrorCorrection> fec_; | |
| 80 std::unique_ptr<FecReceiver> receiver_fec_; | |
| 81 UlpfecPacketGenerator packet_generator_; | |
| 82 }; | |
| 83 | |
| 84 void ReceiverFecTest::EncodeFec( | |
| 85 const ForwardErrorCorrection::PacketList& media_packets, | |
| 86 size_t num_fec_packets, | |
| 87 std::list<ForwardErrorCorrection::Packet*>* fec_packets) { | |
| 88 const uint8_t protection_factor = | |
| 89 num_fec_packets * 255 / media_packets.size(); | |
| 90 // Unequal protection is turned off, and the number of important | |
| 91 // packets is thus irrelevant. | |
| 92 constexpr int kNumImportantPackets = 0; | |
| 93 constexpr bool kUseUnequalProtection = false; | |
| 94 constexpr FecMaskType kFecMaskType = kFecMaskBursty; | |
| 95 EXPECT_EQ( | |
| 96 0, fec_->EncodeFec(media_packets, protection_factor, kNumImportantPackets, | |
| 97 kUseUnequalProtection, kFecMaskType, fec_packets)); | |
| 98 ASSERT_EQ(num_fec_packets, fec_packets->size()); | |
| 99 } | |
| 100 | |
| 101 void ReceiverFecTest::PacketizeFrame( | |
| 102 size_t num_media_packets, | |
| 103 size_t frame_offset, | |
| 104 std::list<AugmentedPacket*>* augmented_packets, | |
| 105 ForwardErrorCorrection::PacketList* packets) { | |
| 106 packet_generator_.NewFrame(num_media_packets); | |
| 107 for (size_t i = 0; i < num_media_packets; ++i) { | |
| 108 std::unique_ptr<AugmentedPacket> next_packet( | |
| 109 packet_generator_.NextPacket(frame_offset + i, kRtpHeaderSize + 10)); | |
| 110 augmented_packets->push_back(next_packet.get()); | |
| 111 packets->push_back(std::move(next_packet)); | |
| 112 } | |
| 113 } | |
| 114 | |
| 115 void ReceiverFecTest::BuildAndAddRedMediaPacket(AugmentedPacket* packet) { | |
| 116 std::unique_ptr<AugmentedPacket> red_packet( | |
| 117 packet_generator_.BuildMediaRedPacket(*packet)); | |
| 118 EXPECT_EQ(0, receiver_fec_->AddReceivedRedPacket( | |
| 119 red_packet->header.header, red_packet->data, | |
| 120 red_packet->length, kFecPayloadType)); | |
| 121 } | |
| 122 | |
| 123 void ReceiverFecTest::BuildAndAddRedFecPacket(Packet* packet) { | |
| 124 std::unique_ptr<AugmentedPacket> red_packet( | |
| 125 packet_generator_.BuildUlpfecRedPacket(*packet)); | |
| 126 EXPECT_EQ(0, receiver_fec_->AddReceivedRedPacket( | |
| 127 red_packet->header.header, red_packet->data, | |
| 128 red_packet->length, kFecPayloadType)); | |
| 129 } | |
| 130 | |
| 131 void ReceiverFecTest::VerifyReconstructedMediaPacket( | |
| 132 const AugmentedPacket& packet, | |
| 133 size_t times) { | |
| 134 // Verify that the content of the reconstructed packet is equal to the | |
| 135 // content of |packet|, and that the same content is received |times| number | |
| 136 // of times in a row. | |
| 137 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, packet.length)) | |
| 138 .With(Args<0, 1>(ElementsAreArray(packet.data, packet.length))) | |
| 139 .Times(times) | |
| 140 .WillRepeatedly(Return(true)); | |
| 141 } | |
| 142 | |
| 143 void ReceiverFecTest::InjectGarbagePacketLength(size_t fec_garbage_offset) { | |
| 144 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _)) | |
| 145 .WillRepeatedly(Return(true)); | |
| 146 | |
| 147 const size_t kNumFecPackets = 1; | |
| 148 std::list<AugmentedPacket*> augmented_media_packets; | |
| 149 ForwardErrorCorrection::PacketList media_packets; | |
| 150 PacketizeFrame(2, 0, &augmented_media_packets, &media_packets); | |
| 151 std::list<ForwardErrorCorrection::Packet*> fec_packets; | |
| 152 EncodeFec(media_packets, kNumFecPackets, &fec_packets); | |
| 153 ByteWriter<uint16_t>::WriteBigEndian( | |
| 154 &fec_packets.front()->data[fec_garbage_offset], 0x4711); | |
| 155 | |
| 156 // Inject first media packet, then first FEC packet, skipping the second media | |
| 157 // packet to cause a recovery from the FEC packet. | |
| 158 BuildAndAddRedMediaPacket(augmented_media_packets.front()); | |
| 159 BuildAndAddRedFecPacket(fec_packets.front()); | |
| 160 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); | |
| 161 | |
| 162 FecPacketCounter counter = receiver_fec_->GetPacketCounter(); | |
| 163 EXPECT_EQ(2U, counter.num_packets); | |
| 164 EXPECT_EQ(1U, counter.num_fec_packets); | |
| 165 EXPECT_EQ(0U, counter.num_recovered_packets); | |
| 166 } | |
| 167 | |
| 168 void ReceiverFecTest::SurvivesMaliciousPacket(const uint8_t* data, | |
| 169 size_t length, | |
| 170 uint8_t ulpfec_payload_type) { | |
| 171 webrtc::RTPHeader header; | |
| 172 std::unique_ptr<webrtc::RtpHeaderParser> parser( | |
| 173 webrtc::RtpHeaderParser::Create()); | |
| 174 ASSERT_TRUE(parser->Parse(data, length, &header)); | |
| 175 | |
| 176 webrtc::NullRtpData null_callback; | |
| 177 std::unique_ptr<webrtc::FecReceiver> receiver_fec( | |
| 178 webrtc::FecReceiver::Create(&null_callback)); | |
| 179 | |
| 180 receiver_fec->AddReceivedRedPacket(header, data, length, ulpfec_payload_type); | |
| 181 } | |
| 182 | |
| 183 TEST_F(ReceiverFecTest, TwoMediaOneFec) { | |
| 184 constexpr size_t kNumFecPackets = 1u; | |
| 185 std::list<AugmentedPacket*> augmented_media_packets; | |
| 186 ForwardErrorCorrection::PacketList media_packets; | |
| 187 PacketizeFrame(2, 0, &augmented_media_packets, &media_packets); | |
| 188 std::list<ForwardErrorCorrection::Packet*> fec_packets; | |
| 189 EncodeFec(media_packets, kNumFecPackets, &fec_packets); | |
| 190 | |
| 191 // Recovery | |
| 192 auto it = augmented_media_packets.begin(); | |
| 193 BuildAndAddRedMediaPacket(*it); | |
| 194 VerifyReconstructedMediaPacket(**it, 1); | |
| 195 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); | |
| 196 // Drop one media packet. | |
| 197 auto fec_it = fec_packets.begin(); | |
| 198 BuildAndAddRedFecPacket(*fec_it); | |
| 199 ++it; | |
| 200 VerifyReconstructedMediaPacket(**it, 1); | |
| 201 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); | |
| 202 | |
| 203 FecPacketCounter counter = receiver_fec_->GetPacketCounter(); | |
| 204 EXPECT_EQ(2u, counter.num_packets); | |
| 205 EXPECT_EQ(1u, counter.num_fec_packets); | |
| 206 EXPECT_EQ(1u, counter.num_recovered_packets); | |
| 207 } | |
| 208 | |
| 209 TEST_F(ReceiverFecTest, InjectGarbageFecHeaderLengthRecovery) { | |
| 210 // Byte offset 8 is the 'length recovery' field of the FEC header. | |
| 211 InjectGarbagePacketLength(8); | |
| 212 } | |
| 213 | |
| 214 TEST_F(ReceiverFecTest, InjectGarbageFecLevelHeaderProtectionLength) { | |
| 215 // Byte offset 10 is the 'protection length' field in the first FEC level | |
| 216 // header. | |
| 217 InjectGarbagePacketLength(10); | |
| 218 } | |
| 219 | |
| 220 TEST_F(ReceiverFecTest, TwoMediaTwoFec) { | |
| 221 const size_t kNumFecPackets = 2; | |
| 222 std::list<AugmentedPacket*> augmented_media_packets; | |
| 223 ForwardErrorCorrection::PacketList media_packets; | |
| 224 PacketizeFrame(2, 0, &augmented_media_packets, &media_packets); | |
| 225 std::list<ForwardErrorCorrection::Packet*> fec_packets; | |
| 226 EncodeFec(media_packets, kNumFecPackets, &fec_packets); | |
| 227 | |
| 228 // Recovery | |
| 229 // Drop both media packets. | |
| 230 auto it = augmented_media_packets.begin(); | |
| 231 auto fec_it = fec_packets.begin(); | |
| 232 BuildAndAddRedFecPacket(*fec_it); | |
| 233 VerifyReconstructedMediaPacket(**it, 1); | |
| 234 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); | |
| 235 ++fec_it; | |
| 236 BuildAndAddRedFecPacket(*fec_it); | |
| 237 ++it; | |
| 238 VerifyReconstructedMediaPacket(**it, 1); | |
| 239 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); | |
| 240 } | |
| 241 | |
| 242 TEST_F(ReceiverFecTest, TwoFramesOneFec) { | |
| 243 const size_t kNumFecPackets = 1; | |
| 244 std::list<AugmentedPacket*> augmented_media_packets; | |
| 245 ForwardErrorCorrection::PacketList media_packets; | |
| 246 PacketizeFrame(1, 0, &augmented_media_packets, &media_packets); | |
| 247 PacketizeFrame(1, 1, &augmented_media_packets, &media_packets); | |
| 248 std::list<ForwardErrorCorrection::Packet*> fec_packets; | |
| 249 EncodeFec(media_packets, kNumFecPackets, &fec_packets); | |
| 250 | |
| 251 // Recovery | |
| 252 auto it = augmented_media_packets.begin(); | |
| 253 BuildAndAddRedMediaPacket(augmented_media_packets.front()); | |
| 254 VerifyReconstructedMediaPacket(**it, 1); | |
| 255 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); | |
| 256 // Drop one media packet. | |
| 257 BuildAndAddRedFecPacket(fec_packets.front()); | |
| 258 ++it; | |
| 259 VerifyReconstructedMediaPacket(**it, 1); | |
| 260 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); | |
| 261 } | |
| 262 | |
| 263 TEST_F(ReceiverFecTest, OneCompleteOneUnrecoverableFrame) { | |
| 264 const size_t kNumFecPackets = 1; | |
| 265 std::list<AugmentedPacket*> augmented_media_packets; | |
| 266 ForwardErrorCorrection::PacketList media_packets; | |
| 267 PacketizeFrame(1, 0, &augmented_media_packets, &media_packets); | |
| 268 PacketizeFrame(2, 1, &augmented_media_packets, &media_packets); | |
| 269 | |
| 270 std::list<ForwardErrorCorrection::Packet*> fec_packets; | |
| 271 EncodeFec(media_packets, kNumFecPackets, &fec_packets); | |
| 272 | |
| 273 // Recovery | |
| 274 auto it = augmented_media_packets.begin(); | |
| 275 BuildAndAddRedMediaPacket(*it); // First frame: one packet. | |
| 276 VerifyReconstructedMediaPacket(**it, 1); | |
| 277 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); | |
| 278 ++it; | |
| 279 BuildAndAddRedMediaPacket(*it); // First packet of second frame. | |
| 280 VerifyReconstructedMediaPacket(**it, 1); | |
| 281 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); | |
| 282 } | |
| 283 | |
| 284 TEST_F(ReceiverFecTest, MaxFramesOneFec) { | |
| 285 const size_t kNumFecPackets = 1; | |
| 286 const size_t kNumMediaPackets = 48; | |
| 287 std::list<AugmentedPacket*> augmented_media_packets; | |
| 288 ForwardErrorCorrection::PacketList media_packets; | |
| 289 for (size_t i = 0; i < kNumMediaPackets; ++i) { | |
| 290 PacketizeFrame(1, i, &augmented_media_packets, &media_packets); | |
| 291 } | |
| 292 std::list<ForwardErrorCorrection::Packet*> fec_packets; | |
| 293 EncodeFec(media_packets, kNumFecPackets, &fec_packets); | |
| 294 | |
| 295 // Recovery | |
| 296 auto it = augmented_media_packets.begin(); | |
| 297 ++it; // Drop first packet. | |
| 298 for (; it != augmented_media_packets.end(); ++it) { | |
| 299 BuildAndAddRedMediaPacket(*it); | |
| 300 VerifyReconstructedMediaPacket(**it, 1); | |
| 301 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); | |
| 302 } | |
| 303 BuildAndAddRedFecPacket(fec_packets.front()); | |
| 304 it = augmented_media_packets.begin(); | |
| 305 VerifyReconstructedMediaPacket(**it, 1); | |
| 306 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); | |
| 307 } | |
| 308 | |
| 309 TEST_F(ReceiverFecTest, TooManyFrames) { | |
| 310 const size_t kNumFecPackets = 1; | |
| 311 const size_t kNumMediaPackets = 49; | |
| 312 std::list<AugmentedPacket*> augmented_media_packets; | |
| 313 ForwardErrorCorrection::PacketList media_packets; | |
| 314 for (size_t i = 0; i < kNumMediaPackets; ++i) { | |
| 315 PacketizeFrame(1, i, &augmented_media_packets, &media_packets); | |
| 316 } | |
| 317 std::list<ForwardErrorCorrection::Packet*> fec_packets; | |
| 318 EXPECT_EQ(-1, fec_->EncodeFec(media_packets, | |
| 319 kNumFecPackets * 255 / kNumMediaPackets, 0, | |
| 320 false, kFecMaskBursty, &fec_packets)); | |
| 321 } | |
| 322 | |
| 323 TEST_F(ReceiverFecTest, PacketNotDroppedTooEarly) { | |
| 324 // 1 frame with 2 media packets and one FEC packet. One media packet missing. | |
| 325 // Delay the FEC packet. | |
| 326 Packet* delayed_fec = nullptr; | |
| 327 const size_t kNumFecPacketsBatch1 = 1; | |
| 328 const size_t kNumMediaPacketsBatch1 = 2; | |
| 329 std::list<AugmentedPacket*> augmented_media_packets_batch1; | |
| 330 ForwardErrorCorrection::PacketList media_packets_batch1; | |
| 331 PacketizeFrame(kNumMediaPacketsBatch1, 0, &augmented_media_packets_batch1, | |
| 332 &media_packets_batch1); | |
| 333 std::list<ForwardErrorCorrection::Packet*> fec_packets; | |
| 334 EncodeFec(media_packets_batch1, kNumFecPacketsBatch1, &fec_packets); | |
| 335 | |
| 336 BuildAndAddRedMediaPacket(augmented_media_packets_batch1.front()); | |
| 337 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _)) | |
| 338 .Times(1).WillRepeatedly(Return(true)); | |
| 339 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); | |
| 340 delayed_fec = fec_packets.front(); | |
| 341 | |
| 342 // Fill the FEC decoder. No packets should be dropped. | |
| 343 const size_t kNumMediaPacketsBatch2 = 46; | |
| 344 std::list<AugmentedPacket*> augmented_media_packets_batch2; | |
| 345 ForwardErrorCorrection::PacketList media_packets_batch2; | |
| 346 for (size_t i = 0; i < kNumMediaPacketsBatch2; ++i) { | |
| 347 PacketizeFrame(1, i, &augmented_media_packets_batch2, | |
| 348 &media_packets_batch2); | |
| 349 } | |
| 350 for (auto it = augmented_media_packets_batch2.begin(); | |
| 351 it != augmented_media_packets_batch2.end(); ++it) { | |
| 352 BuildAndAddRedMediaPacket(*it); | |
| 353 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _)) | |
| 354 .Times(1).WillRepeatedly(Return(true)); | |
| 355 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); | |
| 356 } | |
| 357 | |
| 358 // Add the delayed FEC packet. One packet should be reconstructed. | |
| 359 BuildAndAddRedFecPacket(delayed_fec); | |
| 360 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _)) | |
| 361 .Times(1).WillRepeatedly(Return(true)); | |
| 362 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); | |
| 363 } | |
| 364 | |
| 365 TEST_F(ReceiverFecTest, PacketDroppedWhenTooOld) { | |
| 366 // 1 frame with 2 media packets and one FEC packet. One media packet missing. | |
| 367 // Delay the FEC packet. | |
| 368 Packet* delayed_fec = nullptr; | |
| 369 const size_t kNumFecPacketsBatch1 = 1; | |
| 370 const size_t kNumMediaPacketsBatch1 = 2; | |
| 371 std::list<AugmentedPacket*> augmented_media_packets_batch1; | |
| 372 ForwardErrorCorrection::PacketList media_packets_batch1; | |
| 373 PacketizeFrame(kNumMediaPacketsBatch1, 0, &augmented_media_packets_batch1, | |
| 374 &media_packets_batch1); | |
| 375 std::list<ForwardErrorCorrection::Packet*> fec_packets; | |
| 376 EncodeFec(media_packets_batch1, kNumFecPacketsBatch1, &fec_packets); | |
| 377 | |
| 378 BuildAndAddRedMediaPacket(augmented_media_packets_batch1.front()); | |
| 379 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _)) | |
| 380 .Times(1).WillRepeatedly(Return(true)); | |
| 381 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); | |
| 382 delayed_fec = fec_packets.front(); | |
| 383 | |
| 384 // Fill the FEC decoder and force the last packet to be dropped. | |
| 385 const size_t kNumMediaPacketsBatch2 = 48; | |
| 386 std::list<AugmentedPacket*> augmented_media_packets_batch2; | |
| 387 ForwardErrorCorrection::PacketList media_packets_batch2; | |
| 388 for (size_t i = 0; i < kNumMediaPacketsBatch2; ++i) { | |
| 389 PacketizeFrame(1, i, &augmented_media_packets_batch2, | |
| 390 &media_packets_batch2); | |
| 391 } | |
| 392 for (auto it = augmented_media_packets_batch2.begin(); | |
| 393 it != augmented_media_packets_batch2.end(); ++it) { | |
| 394 BuildAndAddRedMediaPacket(*it); | |
| 395 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _)) | |
| 396 .Times(1).WillRepeatedly(Return(true)); | |
| 397 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); | |
| 398 } | |
| 399 | |
| 400 // Add the delayed FEC packet. No packet should be reconstructed since the | |
| 401 // first media packet of that frame has been dropped due to being too old. | |
| 402 BuildAndAddRedFecPacket(delayed_fec); | |
| 403 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _)) | |
| 404 .Times(0); | |
| 405 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); | |
| 406 } | |
| 407 | |
| 408 TEST_F(ReceiverFecTest, OldFecPacketDropped) { | |
| 409 // 49 frames with 2 media packets and one FEC packet. All media packets | |
| 410 // missing. | |
| 411 const size_t kNumMediaPackets = 49 * 2; | |
| 412 std::list<AugmentedPacket*> augmented_media_packets; | |
| 413 ForwardErrorCorrection::PacketList media_packets; | |
| 414 for (size_t i = 0; i < kNumMediaPackets / 2; ++i) { | |
| 415 std::list<AugmentedPacket*> frame_augmented_media_packets; | |
| 416 ForwardErrorCorrection::PacketList frame_media_packets; | |
| 417 std::list<ForwardErrorCorrection::Packet*> fec_packets; | |
| 418 PacketizeFrame(2, 0, &frame_augmented_media_packets, &frame_media_packets); | |
| 419 EncodeFec(frame_media_packets, 1, &fec_packets); | |
| 420 for (auto it = fec_packets.begin(); it != fec_packets.end(); ++it) { | |
| 421 // Only FEC packets inserted. No packets recoverable at this time. | |
| 422 BuildAndAddRedFecPacket(*it); | |
| 423 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _)) | |
| 424 .Times(0); | |
| 425 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); | |
| 426 } | |
| 427 // Move unique_ptr's to media_packets for lifetime management. | |
| 428 media_packets.insert(media_packets.end(), | |
| 429 std::make_move_iterator(frame_media_packets.begin()), | |
| 430 std::make_move_iterator(frame_media_packets.end())); | |
| 431 augmented_media_packets.insert(augmented_media_packets.end(), | |
| 432 frame_augmented_media_packets.begin(), | |
| 433 frame_augmented_media_packets.end()); | |
| 434 } | |
| 435 // Insert the oldest media packet. The corresponding FEC packet is too old | |
| 436 // and should have been dropped. Only the media packet we inserted will be | |
| 437 // returned. | |
| 438 BuildAndAddRedMediaPacket(augmented_media_packets.front()); | |
| 439 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _)) | |
| 440 .Times(1).WillRepeatedly(Return(true)); | |
| 441 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); | |
| 442 } | |
| 443 | |
| 444 TEST_F(ReceiverFecTest, TruncatedPacketWithFBitSet) { | |
| 445 const uint8_t kTruncatedPacket[] = {0x80, | |
| 446 0x2a, | |
| 447 0x68, | |
| 448 0x71, | |
| 449 0x29, | |
| 450 0xa1, | |
| 451 0x27, | |
| 452 0x3a, | |
| 453 0x29, | |
| 454 0x12, | |
| 455 0x2a, | |
| 456 0x98, | |
| 457 0xe0, | |
| 458 0x29}; | |
| 459 | |
| 460 SurvivesMaliciousPacket(kTruncatedPacket, sizeof(kTruncatedPacket), 100); | |
| 461 } | |
| 462 | |
| 463 TEST_F(ReceiverFecTest, TruncatedPacketWithFBitSetEndingAfterFirstRedHeader) { | |
| 464 const uint8_t kPacket[] = {0x89, | |
| 465 0x27, | |
| 466 0x3a, | |
| 467 0x83, | |
| 468 0x27, | |
| 469 0x3a, | |
| 470 0x3a, | |
| 471 0xf3, | |
| 472 0x67, | |
| 473 0xbe, | |
| 474 0x2a, | |
| 475 0xa9, | |
| 476 0x27, | |
| 477 0x54, | |
| 478 0x3a, | |
| 479 0x3a, | |
| 480 0x2a, | |
| 481 0x67, | |
| 482 0x3a, | |
| 483 0xf3, | |
| 484 0x67, | |
| 485 0xbe, | |
| 486 0x2a, | |
| 487 0x27, | |
| 488 0xe6, | |
| 489 0xf6, | |
| 490 0x03, | |
| 491 0x3e, | |
| 492 0x29, | |
| 493 0x27, | |
| 494 0x21, | |
| 495 0x27, | |
| 496 0x2a, | |
| 497 0x29, | |
| 498 0x21, | |
| 499 0x4b, | |
| 500 0x29, | |
| 501 0x3a, | |
| 502 0x28, | |
| 503 0x29, | |
| 504 0xbf, | |
| 505 0x29, | |
| 506 0x2a, | |
| 507 0x26, | |
| 508 0x29, | |
| 509 0xae, | |
| 510 0x27, | |
| 511 0xa6, | |
| 512 0xf6, | |
| 513 0x00, | |
| 514 0x03, | |
| 515 0x3e}; | |
| 516 SurvivesMaliciousPacket(kPacket, sizeof(kPacket), 100); | |
| 517 } | |
| 518 | |
| 519 TEST_F(ReceiverFecTest, TruncatedPacketWithoutDataPastFirstBlock) { | |
| 520 const uint8_t kPacket[] = {0x82, | |
| 521 0x38, | |
| 522 0x92, | |
| 523 0x38, | |
| 524 0x92, | |
| 525 0x38, | |
| 526 0xde, | |
| 527 0x2a, | |
| 528 0x11, | |
| 529 0xc8, | |
| 530 0xa3, | |
| 531 0xc4, | |
| 532 0x82, | |
| 533 0x38, | |
| 534 0x2a, | |
| 535 0x21, | |
| 536 0x2a, | |
| 537 0x28, | |
| 538 0x92, | |
| 539 0x38, | |
| 540 0x92, | |
| 541 0x00, | |
| 542 0x00, | |
| 543 0x0a, | |
| 544 0x3a, | |
| 545 0xc8, | |
| 546 0xa3, | |
| 547 0x3a, | |
| 548 0x27, | |
| 549 0xc4, | |
| 550 0x2a, | |
| 551 0x21, | |
| 552 0x2a, | |
| 553 0x28}; | |
| 554 SurvivesMaliciousPacket(kPacket, sizeof(kPacket), 100); | |
| 555 } | |
| 556 | |
| 557 } // namespace webrtc | |
| OLD | NEW |