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