| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 23 #include "webrtc/test/gtest.h" | 23 #include "webrtc/test/gtest.h" |
| 24 | 24 |
| 25 namespace webrtc { | 25 namespace webrtc { |
| 26 | 26 |
| 27 namespace { | 27 namespace { |
| 28 using ::testing::_; | 28 using ::testing::_; |
| 29 using ::testing::Args; | 29 using ::testing::Args; |
| 30 using ::testing::ElementsAreArray; | 30 using ::testing::ElementsAreArray; |
| 31 using ::testing::Return; | 31 using ::testing::Return; |
| 32 | 32 |
| 33 using test::fec::AugmentedPacket; |
| 33 using Packet = ForwardErrorCorrection::Packet; | 34 using Packet = ForwardErrorCorrection::Packet; |
| 34 using test::fec::RawRtpPacket; | |
| 35 using test::fec::UlpfecPacketGenerator; | 35 using test::fec::UlpfecPacketGenerator; |
| 36 | 36 |
| 37 constexpr int kFecPayloadType = 96; | 37 constexpr int kFecPayloadType = 96; |
| 38 constexpr uint32_t kMediaSsrc = 835424; |
| 38 } // namespace | 39 } // namespace |
| 39 | 40 |
| 40 class ReceiverFecTest : public ::testing::Test { | 41 class ReceiverFecTest : public ::testing::Test { |
| 41 protected: | 42 protected: |
| 42 ReceiverFecTest() | 43 ReceiverFecTest() |
| 43 : fec_(ForwardErrorCorrection::CreateUlpfec()), | 44 : fec_(ForwardErrorCorrection::CreateUlpfec()), |
| 44 receiver_fec_(FecReceiver::Create(&rtp_data_callback_)) {} | 45 receiver_fec_(FecReceiver::Create(&rtp_data_callback_)), |
| 46 packet_generator_(kMediaSsrc) {} |
| 45 | 47 |
| 46 void EncodeFec(const ForwardErrorCorrection::PacketList& media_packets, | 48 void EncodeFec(const ForwardErrorCorrection::PacketList& media_packets, |
| 47 size_t num_fec_packets, | 49 size_t num_fec_packets, |
| 48 std::list<ForwardErrorCorrection::Packet*>* fec_packets) { | 50 std::list<ForwardErrorCorrection::Packet*>* fec_packets) { |
| 49 uint8_t protection_factor = num_fec_packets * 255 / media_packets.size(); | 51 uint8_t protection_factor = num_fec_packets * 255 / media_packets.size(); |
| 50 EXPECT_EQ(0, fec_->EncodeFec(media_packets, protection_factor, 0, false, | 52 EXPECT_EQ(0, fec_->EncodeFec(media_packets, protection_factor, 0, false, |
| 51 kFecMaskBursty, fec_packets)); | 53 kFecMaskBursty, fec_packets)); |
| 52 ASSERT_EQ(num_fec_packets, fec_packets->size()); | 54 ASSERT_EQ(num_fec_packets, fec_packets->size()); |
| 53 } | 55 } |
| 54 | 56 |
| 55 void GenerateFrame(size_t num_media_packets, | 57 void GenerateFrame(size_t num_media_packets, |
| 56 size_t frame_offset, | 58 size_t frame_offset, |
| 57 std::list<RawRtpPacket*>* media_rtp_packets, | 59 std::list<AugmentedPacket*>* augmented_packets, |
| 58 ForwardErrorCorrection::PacketList* media_packets) { | 60 ForwardErrorCorrection::PacketList* media_packets) { |
| 59 generator_.NewFrame(num_media_packets); | 61 packet_generator_.NewFrame(num_media_packets); |
| 60 for (size_t i = 0; i < num_media_packets; ++i) { | 62 for (size_t i = 0; i < num_media_packets; ++i) { |
| 61 std::unique_ptr<RawRtpPacket> next_packet( | 63 std::unique_ptr<AugmentedPacket> next_packet( |
| 62 generator_.NextPacket(frame_offset + i, kRtpHeaderSize + 10)); | 64 packet_generator_.NextPacket(frame_offset + i, kRtpHeaderSize + 10)); |
| 63 media_rtp_packets->push_back(next_packet.get()); | 65 augmented_packets->push_back(next_packet.get()); |
| 64 media_packets->push_back(std::move(next_packet)); | 66 media_packets->push_back(std::move(next_packet)); |
| 65 } | 67 } |
| 66 } | 68 } |
| 67 | 69 |
| 68 void VerifyReconstructedMediaPacket(const RawRtpPacket& packet, | 70 void VerifyReconstructedMediaPacket(const AugmentedPacket& packet, |
| 69 size_t times) { | 71 size_t times) { |
| 70 // Verify that the content of the reconstructed packet is equal to the | 72 // Verify that the content of the reconstructed packet is equal to the |
| 71 // content of |packet|, and that the same content is received |times| number | 73 // content of |packet|, and that the same content is received |times| number |
| 72 // of times in a row. | 74 // of times in a row. |
| 73 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, packet.length)) | 75 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, packet.length)) |
| 74 .With(Args<0, 1>(ElementsAreArray(packet.data, packet.length))) | 76 .With(Args<0, 1>(ElementsAreArray(packet.data, packet.length))) |
| 75 .Times(times) | 77 .Times(times) |
| 76 .WillRepeatedly(Return(true)); | 78 .WillRepeatedly(Return(true)); |
| 77 } | 79 } |
| 78 | 80 |
| 79 void BuildAndAddRedMediaPacket(RawRtpPacket* packet) { | 81 void BuildAndAddRedMediaPacket(AugmentedPacket* packet) { |
| 80 std::unique_ptr<RawRtpPacket> red_packet( | 82 std::unique_ptr<AugmentedPacket> red_packet( |
| 81 generator_.BuildMediaRedPacket(packet)); | 83 UlpfecPacketGenerator::BuildMediaRedPacket(*packet)); |
| 82 EXPECT_EQ(0, receiver_fec_->AddReceivedRedPacket( | 84 EXPECT_EQ(0, receiver_fec_->AddReceivedRedPacket( |
| 83 red_packet->header.header, red_packet->data, | 85 red_packet->header.header, red_packet->data, |
| 84 red_packet->length, kFecPayloadType)); | 86 red_packet->length, kFecPayloadType)); |
| 85 } | 87 } |
| 86 | 88 |
| 87 void BuildAndAddRedFecPacket(Packet* packet) { | 89 void BuildAndAddRedFecPacket(Packet* packet) { |
| 88 std::unique_ptr<RawRtpPacket> red_packet( | 90 std::unique_ptr<AugmentedPacket> red_packet( |
| 89 generator_.BuildFecRedPacket(packet)); | 91 packet_generator_.BuildUlpfecRedPacket(*packet)); |
| 90 EXPECT_EQ(0, receiver_fec_->AddReceivedRedPacket( | 92 EXPECT_EQ(0, receiver_fec_->AddReceivedRedPacket( |
| 91 red_packet->header.header, red_packet->data, | 93 red_packet->header.header, red_packet->data, |
| 92 red_packet->length, kFecPayloadType)); | 94 red_packet->length, kFecPayloadType)); |
| 93 } | 95 } |
| 94 | 96 |
| 95 void InjectGarbagePacketLength(size_t fec_garbage_offset); | 97 void InjectGarbagePacketLength(size_t fec_garbage_offset); |
| 96 static void SurvivesMaliciousPacket(const uint8_t* data, | 98 static void SurvivesMaliciousPacket(const uint8_t* data, |
| 97 size_t length, | 99 size_t length, |
| 98 uint8_t ulpfec_payload_type); | 100 uint8_t ulpfec_payload_type); |
| 99 | 101 |
| 100 MockRtpData rtp_data_callback_; | 102 MockRtpData rtp_data_callback_; |
| 101 std::unique_ptr<ForwardErrorCorrection> fec_; | 103 std::unique_ptr<ForwardErrorCorrection> fec_; |
| 102 std::unique_ptr<FecReceiver> receiver_fec_; | 104 std::unique_ptr<FecReceiver> receiver_fec_; |
| 103 UlpfecPacketGenerator generator_; | 105 UlpfecPacketGenerator packet_generator_; |
| 104 }; | 106 }; |
| 105 | 107 |
| 106 TEST_F(ReceiverFecTest, TwoMediaOneFec) { | 108 TEST_F(ReceiverFecTest, TwoMediaOneFec) { |
| 107 const size_t kNumFecPackets = 1; | 109 const size_t kNumFecPackets = 1; |
| 108 std::list<RawRtpPacket*> media_rtp_packets; | 110 std::list<AugmentedPacket*> augmented_media_packets; |
| 109 ForwardErrorCorrection::PacketList media_packets; | 111 ForwardErrorCorrection::PacketList media_packets; |
| 110 GenerateFrame(2, 0, &media_rtp_packets, &media_packets); | 112 GenerateFrame(2, 0, &augmented_media_packets, &media_packets); |
| 111 std::list<ForwardErrorCorrection::Packet*> fec_packets; | 113 std::list<ForwardErrorCorrection::Packet*> fec_packets; |
| 112 EncodeFec(media_packets, kNumFecPackets, &fec_packets); | 114 EncodeFec(media_packets, kNumFecPackets, &fec_packets); |
| 113 | 115 |
| 114 // Recovery | 116 // Recovery |
| 115 auto it = media_rtp_packets.begin(); | 117 auto it = augmented_media_packets.begin(); |
| 116 BuildAndAddRedMediaPacket(*it); | 118 BuildAndAddRedMediaPacket(*it); |
| 117 VerifyReconstructedMediaPacket(**it, 1); | 119 VerifyReconstructedMediaPacket(**it, 1); |
| 118 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); | 120 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); |
| 119 // Drop one media packet. | 121 // Drop one media packet. |
| 120 auto fec_it = fec_packets.begin(); | 122 auto fec_it = fec_packets.begin(); |
| 121 BuildAndAddRedFecPacket(*fec_it); | 123 BuildAndAddRedFecPacket(*fec_it); |
| 122 ++it; | 124 ++it; |
| 123 VerifyReconstructedMediaPacket(**it, 1); | 125 VerifyReconstructedMediaPacket(**it, 1); |
| 124 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); | 126 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); |
| 125 | 127 |
| 126 FecPacketCounter counter = receiver_fec_->GetPacketCounter(); | 128 FecPacketCounter counter = receiver_fec_->GetPacketCounter(); |
| 127 EXPECT_EQ(2U, counter.num_packets); | 129 EXPECT_EQ(2U, counter.num_packets); |
| 128 EXPECT_EQ(1U, counter.num_fec_packets); | 130 EXPECT_EQ(1U, counter.num_fec_packets); |
| 129 EXPECT_EQ(1U, counter.num_recovered_packets); | 131 EXPECT_EQ(1U, counter.num_recovered_packets); |
| 130 } | 132 } |
| 131 | 133 |
| 132 void ReceiverFecTest::InjectGarbagePacketLength(size_t fec_garbage_offset) { | 134 void ReceiverFecTest::InjectGarbagePacketLength(size_t fec_garbage_offset) { |
| 133 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _)) | 135 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _)) |
| 134 .WillRepeatedly(Return(true)); | 136 .WillRepeatedly(Return(true)); |
| 135 | 137 |
| 136 const size_t kNumFecPackets = 1; | 138 const size_t kNumFecPackets = 1; |
| 137 std::list<RawRtpPacket*> media_rtp_packets; | 139 std::list<AugmentedPacket*> augmented_media_packets; |
| 138 ForwardErrorCorrection::PacketList media_packets; | 140 ForwardErrorCorrection::PacketList media_packets; |
| 139 GenerateFrame(2, 0, &media_rtp_packets, &media_packets); | 141 GenerateFrame(2, 0, &augmented_media_packets, &media_packets); |
| 140 std::list<ForwardErrorCorrection::Packet*> fec_packets; | 142 std::list<ForwardErrorCorrection::Packet*> fec_packets; |
| 141 EncodeFec(media_packets, kNumFecPackets, &fec_packets); | 143 EncodeFec(media_packets, kNumFecPackets, &fec_packets); |
| 142 ByteWriter<uint16_t>::WriteBigEndian( | 144 ByteWriter<uint16_t>::WriteBigEndian( |
| 143 &fec_packets.front()->data[fec_garbage_offset], 0x4711); | 145 &fec_packets.front()->data[fec_garbage_offset], 0x4711); |
| 144 | 146 |
| 145 // Inject first media packet, then first FEC packet, skipping the second media | 147 // Inject first media packet, then first FEC packet, skipping the second media |
| 146 // packet to cause a recovery from the FEC packet. | 148 // packet to cause a recovery from the FEC packet. |
| 147 BuildAndAddRedMediaPacket(media_rtp_packets.front()); | 149 BuildAndAddRedMediaPacket(augmented_media_packets.front()); |
| 148 BuildAndAddRedFecPacket(fec_packets.front()); | 150 BuildAndAddRedFecPacket(fec_packets.front()); |
| 149 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); | 151 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); |
| 150 | 152 |
| 151 FecPacketCounter counter = receiver_fec_->GetPacketCounter(); | 153 FecPacketCounter counter = receiver_fec_->GetPacketCounter(); |
| 152 EXPECT_EQ(2U, counter.num_packets); | 154 EXPECT_EQ(2U, counter.num_packets); |
| 153 EXPECT_EQ(1U, counter.num_fec_packets); | 155 EXPECT_EQ(1U, counter.num_fec_packets); |
| 154 EXPECT_EQ(0U, counter.num_recovered_packets); | 156 EXPECT_EQ(0U, counter.num_recovered_packets); |
| 155 } | 157 } |
| 156 | 158 |
| 157 TEST_F(ReceiverFecTest, InjectGarbageFecHeaderLengthRecovery) { | 159 TEST_F(ReceiverFecTest, InjectGarbageFecHeaderLengthRecovery) { |
| 158 // Byte offset 8 is the 'length recovery' field of the FEC header. | 160 // Byte offset 8 is the 'length recovery' field of the FEC header. |
| 159 InjectGarbagePacketLength(8); | 161 InjectGarbagePacketLength(8); |
| 160 } | 162 } |
| 161 | 163 |
| 162 TEST_F(ReceiverFecTest, InjectGarbageFecLevelHeaderProtectionLength) { | 164 TEST_F(ReceiverFecTest, InjectGarbageFecLevelHeaderProtectionLength) { |
| 163 // Byte offset 10 is the 'protection length' field in the first FEC level | 165 // Byte offset 10 is the 'protection length' field in the first FEC level |
| 164 // header. | 166 // header. |
| 165 InjectGarbagePacketLength(10); | 167 InjectGarbagePacketLength(10); |
| 166 } | 168 } |
| 167 | 169 |
| 168 TEST_F(ReceiverFecTest, TwoMediaTwoFec) { | 170 TEST_F(ReceiverFecTest, TwoMediaTwoFec) { |
| 169 const size_t kNumFecPackets = 2; | 171 const size_t kNumFecPackets = 2; |
| 170 std::list<RawRtpPacket*> media_rtp_packets; | 172 std::list<AugmentedPacket*> augmented_media_packets; |
| 171 ForwardErrorCorrection::PacketList media_packets; | 173 ForwardErrorCorrection::PacketList media_packets; |
| 172 GenerateFrame(2, 0, &media_rtp_packets, &media_packets); | 174 GenerateFrame(2, 0, &augmented_media_packets, &media_packets); |
| 173 std::list<ForwardErrorCorrection::Packet*> fec_packets; | 175 std::list<ForwardErrorCorrection::Packet*> fec_packets; |
| 174 EncodeFec(media_packets, kNumFecPackets, &fec_packets); | 176 EncodeFec(media_packets, kNumFecPackets, &fec_packets); |
| 175 | 177 |
| 176 // Recovery | 178 // Recovery |
| 177 // Drop both media packets. | 179 // Drop both media packets. |
| 178 auto it = media_rtp_packets.begin(); | 180 auto it = augmented_media_packets.begin(); |
| 179 auto fec_it = fec_packets.begin(); | 181 auto fec_it = fec_packets.begin(); |
| 180 BuildAndAddRedFecPacket(*fec_it); | 182 BuildAndAddRedFecPacket(*fec_it); |
| 181 VerifyReconstructedMediaPacket(**it, 1); | 183 VerifyReconstructedMediaPacket(**it, 1); |
| 182 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); | 184 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); |
| 183 ++fec_it; | 185 ++fec_it; |
| 184 BuildAndAddRedFecPacket(*fec_it); | 186 BuildAndAddRedFecPacket(*fec_it); |
| 185 ++it; | 187 ++it; |
| 186 VerifyReconstructedMediaPacket(**it, 1); | 188 VerifyReconstructedMediaPacket(**it, 1); |
| 187 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); | 189 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); |
| 188 } | 190 } |
| 189 | 191 |
| 190 TEST_F(ReceiverFecTest, TwoFramesOneFec) { | 192 TEST_F(ReceiverFecTest, TwoFramesOneFec) { |
| 191 const size_t kNumFecPackets = 1; | 193 const size_t kNumFecPackets = 1; |
| 192 std::list<RawRtpPacket*> media_rtp_packets; | 194 std::list<AugmentedPacket*> augmented_media_packets; |
| 193 ForwardErrorCorrection::PacketList media_packets; | 195 ForwardErrorCorrection::PacketList media_packets; |
| 194 GenerateFrame(1, 0, &media_rtp_packets, &media_packets); | 196 GenerateFrame(1, 0, &augmented_media_packets, &media_packets); |
| 195 GenerateFrame(1, 1, &media_rtp_packets, &media_packets); | 197 GenerateFrame(1, 1, &augmented_media_packets, &media_packets); |
| 196 std::list<ForwardErrorCorrection::Packet*> fec_packets; | 198 std::list<ForwardErrorCorrection::Packet*> fec_packets; |
| 197 EncodeFec(media_packets, kNumFecPackets, &fec_packets); | 199 EncodeFec(media_packets, kNumFecPackets, &fec_packets); |
| 198 | 200 |
| 199 // Recovery | 201 // Recovery |
| 200 auto it = media_rtp_packets.begin(); | 202 auto it = augmented_media_packets.begin(); |
| 201 BuildAndAddRedMediaPacket(media_rtp_packets.front()); | 203 BuildAndAddRedMediaPacket(augmented_media_packets.front()); |
| 202 VerifyReconstructedMediaPacket(**it, 1); | 204 VerifyReconstructedMediaPacket(**it, 1); |
| 203 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); | 205 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); |
| 204 // Drop one media packet. | 206 // Drop one media packet. |
| 205 BuildAndAddRedFecPacket(fec_packets.front()); | 207 BuildAndAddRedFecPacket(fec_packets.front()); |
| 206 ++it; | 208 ++it; |
| 207 VerifyReconstructedMediaPacket(**it, 1); | 209 VerifyReconstructedMediaPacket(**it, 1); |
| 208 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); | 210 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); |
| 209 } | 211 } |
| 210 | 212 |
| 211 TEST_F(ReceiverFecTest, OneCompleteOneUnrecoverableFrame) { | 213 TEST_F(ReceiverFecTest, OneCompleteOneUnrecoverableFrame) { |
| 212 const size_t kNumFecPackets = 1; | 214 const size_t kNumFecPackets = 1; |
| 213 std::list<RawRtpPacket*> media_rtp_packets; | 215 std::list<AugmentedPacket*> augmented_media_packets; |
| 214 ForwardErrorCorrection::PacketList media_packets; | 216 ForwardErrorCorrection::PacketList media_packets; |
| 215 GenerateFrame(1, 0, &media_rtp_packets, &media_packets); | 217 GenerateFrame(1, 0, &augmented_media_packets, &media_packets); |
| 216 GenerateFrame(2, 1, &media_rtp_packets, &media_packets); | 218 GenerateFrame(2, 1, &augmented_media_packets, &media_packets); |
| 217 | 219 |
| 218 std::list<ForwardErrorCorrection::Packet*> fec_packets; | 220 std::list<ForwardErrorCorrection::Packet*> fec_packets; |
| 219 EncodeFec(media_packets, kNumFecPackets, &fec_packets); | 221 EncodeFec(media_packets, kNumFecPackets, &fec_packets); |
| 220 | 222 |
| 221 // Recovery | 223 // Recovery |
| 222 auto it = media_rtp_packets.begin(); | 224 auto it = augmented_media_packets.begin(); |
| 223 BuildAndAddRedMediaPacket(*it); // First frame: one packet. | 225 BuildAndAddRedMediaPacket(*it); // First frame: one packet. |
| 224 VerifyReconstructedMediaPacket(**it, 1); | 226 VerifyReconstructedMediaPacket(**it, 1); |
| 225 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); | 227 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); |
| 226 ++it; | 228 ++it; |
| 227 BuildAndAddRedMediaPacket(*it); // First packet of second frame. | 229 BuildAndAddRedMediaPacket(*it); // First packet of second frame. |
| 228 VerifyReconstructedMediaPacket(**it, 1); | 230 VerifyReconstructedMediaPacket(**it, 1); |
| 229 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); | 231 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); |
| 230 } | 232 } |
| 231 | 233 |
| 232 TEST_F(ReceiverFecTest, MaxFramesOneFec) { | 234 TEST_F(ReceiverFecTest, MaxFramesOneFec) { |
| 233 const size_t kNumFecPackets = 1; | 235 const size_t kNumFecPackets = 1; |
| 234 const size_t kNumMediaPackets = 48; | 236 const size_t kNumMediaPackets = 48; |
| 235 std::list<RawRtpPacket*> media_rtp_packets; | 237 std::list<AugmentedPacket*> augmented_media_packets; |
| 236 ForwardErrorCorrection::PacketList media_packets; | 238 ForwardErrorCorrection::PacketList media_packets; |
| 237 for (size_t i = 0; i < kNumMediaPackets; ++i) { | 239 for (size_t i = 0; i < kNumMediaPackets; ++i) { |
| 238 GenerateFrame(1, i, &media_rtp_packets, &media_packets); | 240 GenerateFrame(1, i, &augmented_media_packets, &media_packets); |
| 239 } | 241 } |
| 240 std::list<ForwardErrorCorrection::Packet*> fec_packets; | 242 std::list<ForwardErrorCorrection::Packet*> fec_packets; |
| 241 EncodeFec(media_packets, kNumFecPackets, &fec_packets); | 243 EncodeFec(media_packets, kNumFecPackets, &fec_packets); |
| 242 | 244 |
| 243 // Recovery | 245 // Recovery |
| 244 auto it = media_rtp_packets.begin(); | 246 auto it = augmented_media_packets.begin(); |
| 245 ++it; // Drop first packet. | 247 ++it; // Drop first packet. |
| 246 for (; it != media_rtp_packets.end(); ++it) { | 248 for (; it != augmented_media_packets.end(); ++it) { |
| 247 BuildAndAddRedMediaPacket(*it); | 249 BuildAndAddRedMediaPacket(*it); |
| 248 VerifyReconstructedMediaPacket(**it, 1); | 250 VerifyReconstructedMediaPacket(**it, 1); |
| 249 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); | 251 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); |
| 250 } | 252 } |
| 251 BuildAndAddRedFecPacket(fec_packets.front()); | 253 BuildAndAddRedFecPacket(fec_packets.front()); |
| 252 it = media_rtp_packets.begin(); | 254 it = augmented_media_packets.begin(); |
| 253 VerifyReconstructedMediaPacket(**it, 1); | 255 VerifyReconstructedMediaPacket(**it, 1); |
| 254 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); | 256 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); |
| 255 } | 257 } |
| 256 | 258 |
| 257 TEST_F(ReceiverFecTest, TooManyFrames) { | 259 TEST_F(ReceiverFecTest, TooManyFrames) { |
| 258 const size_t kNumFecPackets = 1; | 260 const size_t kNumFecPackets = 1; |
| 259 const size_t kNumMediaPackets = 49; | 261 const size_t kNumMediaPackets = 49; |
| 260 std::list<RawRtpPacket*> media_rtp_packets; | 262 std::list<AugmentedPacket*> augmented_media_packets; |
| 261 ForwardErrorCorrection::PacketList media_packets; | 263 ForwardErrorCorrection::PacketList media_packets; |
| 262 for (size_t i = 0; i < kNumMediaPackets; ++i) { | 264 for (size_t i = 0; i < kNumMediaPackets; ++i) { |
| 263 GenerateFrame(1, i, &media_rtp_packets, &media_packets); | 265 GenerateFrame(1, i, &augmented_media_packets, &media_packets); |
| 264 } | 266 } |
| 265 std::list<ForwardErrorCorrection::Packet*> fec_packets; | 267 std::list<ForwardErrorCorrection::Packet*> fec_packets; |
| 266 EXPECT_EQ(-1, fec_->EncodeFec(media_packets, | 268 EXPECT_EQ(-1, fec_->EncodeFec(media_packets, |
| 267 kNumFecPackets * 255 / kNumMediaPackets, 0, | 269 kNumFecPackets * 255 / kNumMediaPackets, 0, |
| 268 false, kFecMaskBursty, &fec_packets)); | 270 false, kFecMaskBursty, &fec_packets)); |
| 269 } | 271 } |
| 270 | 272 |
| 271 TEST_F(ReceiverFecTest, PacketNotDroppedTooEarly) { | 273 TEST_F(ReceiverFecTest, PacketNotDroppedTooEarly) { |
| 272 // 1 frame with 2 media packets and one FEC packet. One media packet missing. | 274 // 1 frame with 2 media packets and one FEC packet. One media packet missing. |
| 273 // Delay the FEC packet. | 275 // Delay the FEC packet. |
| 274 Packet* delayed_fec = nullptr; | 276 Packet* delayed_fec = nullptr; |
| 275 const size_t kNumFecPacketsBatch1 = 1; | 277 const size_t kNumFecPacketsBatch1 = 1; |
| 276 const size_t kNumMediaPacketsBatch1 = 2; | 278 const size_t kNumMediaPacketsBatch1 = 2; |
| 277 std::list<RawRtpPacket*> media_rtp_packets_batch1; | 279 std::list<AugmentedPacket*> augmented_media_packets_batch1; |
| 278 ForwardErrorCorrection::PacketList media_packets_batch1; | 280 ForwardErrorCorrection::PacketList media_packets_batch1; |
| 279 GenerateFrame(kNumMediaPacketsBatch1, 0, &media_rtp_packets_batch1, | 281 GenerateFrame(kNumMediaPacketsBatch1, 0, &augmented_media_packets_batch1, |
| 280 &media_packets_batch1); | 282 &media_packets_batch1); |
| 281 std::list<ForwardErrorCorrection::Packet*> fec_packets; | 283 std::list<ForwardErrorCorrection::Packet*> fec_packets; |
| 282 EncodeFec(media_packets_batch1, kNumFecPacketsBatch1, &fec_packets); | 284 EncodeFec(media_packets_batch1, kNumFecPacketsBatch1, &fec_packets); |
| 283 | 285 |
| 284 BuildAndAddRedMediaPacket(media_rtp_packets_batch1.front()); | 286 BuildAndAddRedMediaPacket(augmented_media_packets_batch1.front()); |
| 285 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _)) | 287 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _)) |
| 286 .Times(1).WillRepeatedly(Return(true)); | 288 .Times(1).WillRepeatedly(Return(true)); |
| 287 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); | 289 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); |
| 288 delayed_fec = fec_packets.front(); | 290 delayed_fec = fec_packets.front(); |
| 289 | 291 |
| 290 // Fill the FEC decoder. No packets should be dropped. | 292 // Fill the FEC decoder. No packets should be dropped. |
| 291 const size_t kNumMediaPacketsBatch2 = 46; | 293 const size_t kNumMediaPacketsBatch2 = 46; |
| 292 std::list<RawRtpPacket*> media_rtp_packets_batch2; | 294 std::list<AugmentedPacket*> augmented_media_packets_batch2; |
| 293 ForwardErrorCorrection::PacketList media_packets_batch2; | 295 ForwardErrorCorrection::PacketList media_packets_batch2; |
| 294 for (size_t i = 0; i < kNumMediaPacketsBatch2; ++i) { | 296 for (size_t i = 0; i < kNumMediaPacketsBatch2; ++i) { |
| 295 GenerateFrame(1, i, &media_rtp_packets_batch2, &media_packets_batch2); | 297 GenerateFrame(1, i, &augmented_media_packets_batch2, &media_packets_batch2); |
| 296 } | 298 } |
| 297 for (auto it = media_rtp_packets_batch2.begin(); | 299 for (auto it = augmented_media_packets_batch2.begin(); |
| 298 it != media_rtp_packets_batch2.end(); ++it) { | 300 it != augmented_media_packets_batch2.end(); ++it) { |
| 299 BuildAndAddRedMediaPacket(*it); | 301 BuildAndAddRedMediaPacket(*it); |
| 300 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _)) | 302 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _)) |
| 301 .Times(1).WillRepeatedly(Return(true)); | 303 .Times(1).WillRepeatedly(Return(true)); |
| 302 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); | 304 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); |
| 303 } | 305 } |
| 304 | 306 |
| 305 // Add the delayed FEC packet. One packet should be reconstructed. | 307 // Add the delayed FEC packet. One packet should be reconstructed. |
| 306 BuildAndAddRedFecPacket(delayed_fec); | 308 BuildAndAddRedFecPacket(delayed_fec); |
| 307 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _)) | 309 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _)) |
| 308 .Times(1).WillRepeatedly(Return(true)); | 310 .Times(1).WillRepeatedly(Return(true)); |
| 309 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); | 311 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); |
| 310 } | 312 } |
| 311 | 313 |
| 312 TEST_F(ReceiverFecTest, PacketDroppedWhenTooOld) { | 314 TEST_F(ReceiverFecTest, PacketDroppedWhenTooOld) { |
| 313 // 1 frame with 2 media packets and one FEC packet. One media packet missing. | 315 // 1 frame with 2 media packets and one FEC packet. One media packet missing. |
| 314 // Delay the FEC packet. | 316 // Delay the FEC packet. |
| 315 Packet* delayed_fec = nullptr; | 317 Packet* delayed_fec = nullptr; |
| 316 const size_t kNumFecPacketsBatch1 = 1; | 318 const size_t kNumFecPacketsBatch1 = 1; |
| 317 const size_t kNumMediaPacketsBatch1 = 2; | 319 const size_t kNumMediaPacketsBatch1 = 2; |
| 318 std::list<RawRtpPacket*> media_rtp_packets_batch1; | 320 std::list<AugmentedPacket*> augmented_media_packets_batch1; |
| 319 ForwardErrorCorrection::PacketList media_packets_batch1; | 321 ForwardErrorCorrection::PacketList media_packets_batch1; |
| 320 GenerateFrame(kNumMediaPacketsBatch1, 0, &media_rtp_packets_batch1, | 322 GenerateFrame(kNumMediaPacketsBatch1, 0, &augmented_media_packets_batch1, |
| 321 &media_packets_batch1); | 323 &media_packets_batch1); |
| 322 std::list<ForwardErrorCorrection::Packet*> fec_packets; | 324 std::list<ForwardErrorCorrection::Packet*> fec_packets; |
| 323 EncodeFec(media_packets_batch1, kNumFecPacketsBatch1, &fec_packets); | 325 EncodeFec(media_packets_batch1, kNumFecPacketsBatch1, &fec_packets); |
| 324 | 326 |
| 325 BuildAndAddRedMediaPacket(media_rtp_packets_batch1.front()); | 327 BuildAndAddRedMediaPacket(augmented_media_packets_batch1.front()); |
| 326 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _)) | 328 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _)) |
| 327 .Times(1).WillRepeatedly(Return(true)); | 329 .Times(1).WillRepeatedly(Return(true)); |
| 328 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); | 330 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); |
| 329 delayed_fec = fec_packets.front(); | 331 delayed_fec = fec_packets.front(); |
| 330 | 332 |
| 331 // Fill the FEC decoder and force the last packet to be dropped. | 333 // Fill the FEC decoder and force the last packet to be dropped. |
| 332 const size_t kNumMediaPacketsBatch2 = 48; | 334 const size_t kNumMediaPacketsBatch2 = 48; |
| 333 std::list<RawRtpPacket*> media_rtp_packets_batch2; | 335 std::list<AugmentedPacket*> augmented_media_packets_batch2; |
| 334 ForwardErrorCorrection::PacketList media_packets_batch2; | 336 ForwardErrorCorrection::PacketList media_packets_batch2; |
| 335 for (size_t i = 0; i < kNumMediaPacketsBatch2; ++i) { | 337 for (size_t i = 0; i < kNumMediaPacketsBatch2; ++i) { |
| 336 GenerateFrame(1, i, &media_rtp_packets_batch2, &media_packets_batch2); | 338 GenerateFrame(1, i, &augmented_media_packets_batch2, &media_packets_batch2); |
| 337 } | 339 } |
| 338 for (auto it = media_rtp_packets_batch2.begin(); | 340 for (auto it = augmented_media_packets_batch2.begin(); |
| 339 it != media_rtp_packets_batch2.end(); ++it) { | 341 it != augmented_media_packets_batch2.end(); ++it) { |
| 340 BuildAndAddRedMediaPacket(*it); | 342 BuildAndAddRedMediaPacket(*it); |
| 341 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _)) | 343 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _)) |
| 342 .Times(1).WillRepeatedly(Return(true)); | 344 .Times(1).WillRepeatedly(Return(true)); |
| 343 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); | 345 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); |
| 344 } | 346 } |
| 345 | 347 |
| 346 // Add the delayed FEC packet. No packet should be reconstructed since the | 348 // Add the delayed FEC packet. No packet should be reconstructed since the |
| 347 // first media packet of that frame has been dropped due to being too old. | 349 // first media packet of that frame has been dropped due to being too old. |
| 348 BuildAndAddRedFecPacket(delayed_fec); | 350 BuildAndAddRedFecPacket(delayed_fec); |
| 349 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _)) | 351 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _)) |
| 350 .Times(0); | 352 .Times(0); |
| 351 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); | 353 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); |
| 352 } | 354 } |
| 353 | 355 |
| 354 TEST_F(ReceiverFecTest, OldFecPacketDropped) { | 356 TEST_F(ReceiverFecTest, OldFecPacketDropped) { |
| 355 // 49 frames with 2 media packets and one FEC packet. All media packets | 357 // 49 frames with 2 media packets and one FEC packet. All media packets |
| 356 // missing. | 358 // missing. |
| 357 const size_t kNumMediaPackets = 49 * 2; | 359 const size_t kNumMediaPackets = 49 * 2; |
| 358 std::list<RawRtpPacket*> media_rtp_packets; | 360 std::list<AugmentedPacket*> augmented_media_packets; |
| 359 ForwardErrorCorrection::PacketList media_packets; | 361 ForwardErrorCorrection::PacketList media_packets; |
| 360 for (size_t i = 0; i < kNumMediaPackets / 2; ++i) { | 362 for (size_t i = 0; i < kNumMediaPackets / 2; ++i) { |
| 361 std::list<RawRtpPacket*> frame_media_rtp_packets; | 363 std::list<AugmentedPacket*> frame_augmented_media_packets; |
| 362 ForwardErrorCorrection::PacketList frame_media_packets; | 364 ForwardErrorCorrection::PacketList frame_media_packets; |
| 363 std::list<ForwardErrorCorrection::Packet*> fec_packets; | 365 std::list<ForwardErrorCorrection::Packet*> fec_packets; |
| 364 GenerateFrame(2, 0, &frame_media_rtp_packets, &frame_media_packets); | 366 GenerateFrame(2, 0, &frame_augmented_media_packets, &frame_media_packets); |
| 365 EncodeFec(frame_media_packets, 1, &fec_packets); | 367 EncodeFec(frame_media_packets, 1, &fec_packets); |
| 366 for (auto it = fec_packets.begin(); it != fec_packets.end(); ++it) { | 368 for (auto it = fec_packets.begin(); it != fec_packets.end(); ++it) { |
| 367 // Only FEC packets inserted. No packets recoverable at this time. | 369 // Only FEC packets inserted. No packets recoverable at this time. |
| 368 BuildAndAddRedFecPacket(*it); | 370 BuildAndAddRedFecPacket(*it); |
| 369 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _)) | 371 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _)) |
| 370 .Times(0); | 372 .Times(0); |
| 371 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); | 373 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); |
| 372 } | 374 } |
| 373 // Move unique_ptr's to media_packets for lifetime management. | 375 // Move unique_ptr's to media_packets for lifetime management. |
| 374 media_packets.insert(media_packets.end(), | 376 media_packets.insert(media_packets.end(), |
| 375 std::make_move_iterator(frame_media_packets.begin()), | 377 std::make_move_iterator(frame_media_packets.begin()), |
| 376 std::make_move_iterator(frame_media_packets.end())); | 378 std::make_move_iterator(frame_media_packets.end())); |
| 377 media_rtp_packets.insert(media_rtp_packets.end(), | 379 augmented_media_packets.insert(augmented_media_packets.end(), |
| 378 frame_media_rtp_packets.begin(), | 380 frame_augmented_media_packets.begin(), |
| 379 frame_media_rtp_packets.end()); | 381 frame_augmented_media_packets.end()); |
| 380 } | 382 } |
| 381 // Insert the oldest media packet. The corresponding FEC packet is too old | 383 // Insert the oldest media packet. The corresponding FEC packet is too old |
| 382 // and should have been dropped. Only the media packet we inserted will be | 384 // and should have been dropped. Only the media packet we inserted will be |
| 383 // returned. | 385 // returned. |
| 384 BuildAndAddRedMediaPacket(media_rtp_packets.front()); | 386 BuildAndAddRedMediaPacket(augmented_media_packets.front()); |
| 385 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _)) | 387 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _)) |
| 386 .Times(1).WillRepeatedly(Return(true)); | 388 .Times(1).WillRepeatedly(Return(true)); |
| 387 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); | 389 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); |
| 388 } | 390 } |
| 389 | 391 |
| 390 void ReceiverFecTest::SurvivesMaliciousPacket(const uint8_t* data, | 392 void ReceiverFecTest::SurvivesMaliciousPacket(const uint8_t* data, |
| 391 size_t length, | 393 size_t length, |
| 392 uint8_t ulpfec_payload_type) { | 394 uint8_t ulpfec_payload_type) { |
| 393 webrtc::RTPHeader header; | 395 webrtc::RTPHeader header; |
| 394 std::unique_ptr<webrtc::RtpHeaderParser> parser( | 396 std::unique_ptr<webrtc::RtpHeaderParser> parser( |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 509 0x27, | 511 0x27, |
| 510 0xc4, | 512 0xc4, |
| 511 0x2a, | 513 0x2a, |
| 512 0x21, | 514 0x21, |
| 513 0x2a, | 515 0x2a, |
| 514 0x28}; | 516 0x28}; |
| 515 SurvivesMaliciousPacket(kPacket, sizeof(kPacket), 100); | 517 SurvivesMaliciousPacket(kPacket, sizeof(kPacket), 100); |
| 516 } | 518 } |
| 517 | 519 |
| 518 } // namespace webrtc | 520 } // namespace webrtc |
| OLD | NEW |