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 <algorithm> | 11 #include <algorithm> |
12 #include <list> | 12 #include <list> |
13 #include <memory> | 13 #include <memory> |
14 | 14 |
15 #include "webrtc/test/gtest.h" | |
16 #include "webrtc/base/basictypes.h" | 15 #include "webrtc/base/basictypes.h" |
17 #include "webrtc/base/random.h" | 16 #include "webrtc/base/random.h" |
18 #include "webrtc/modules/rtp_rtcp/source/byte_io.h" | 17 #include "webrtc/modules/rtp_rtcp/source/byte_io.h" |
19 #include "webrtc/modules/rtp_rtcp/source/fec_test_helper.h" | 18 #include "webrtc/modules/rtp_rtcp/source/fec_test_helper.h" |
| 19 #include "webrtc/modules/rtp_rtcp/source/flexfec_header_reader_writer.h" |
20 #include "webrtc/modules/rtp_rtcp/source/forward_error_correction.h" | 20 #include "webrtc/modules/rtp_rtcp/source/forward_error_correction.h" |
21 #include "webrtc/modules/rtp_rtcp/source/ulpfec_header_reader_writer.h" | 21 #include "webrtc/modules/rtp_rtcp/source/ulpfec_header_reader_writer.h" |
| 22 #include "webrtc/test/gtest.h" |
22 | 23 |
23 namespace webrtc { | 24 namespace webrtc { |
24 | 25 |
25 namespace { | 26 namespace { |
26 | 27 |
27 // Transport header size in bytes. Assume UDP/IPv4 as a reasonable minimum. | 28 // Transport header size in bytes. Assume UDP/IPv4 as a reasonable minimum. |
28 constexpr size_t kTransportOverhead = 28; | 29 constexpr size_t kTransportOverhead = 28; |
29 | 30 |
30 constexpr uint32_t kMediaSsrc = 83542; | 31 constexpr uint32_t kMediaSsrc = 83542; |
| 32 constexpr uint32_t kFlexfecSsrc = 43245; |
31 | 33 |
32 // Deep copies |src| to |dst|, but only keeps every Nth packet. | 34 // Deep copies |src| to |dst|, but only keeps every Nth packet. |
33 void DeepCopyEveryNthPacket(const ForwardErrorCorrection::PacketList& src, | 35 void DeepCopyEveryNthPacket(const ForwardErrorCorrection::PacketList& src, |
34 int n, | 36 int n, |
35 ForwardErrorCorrection::PacketList* dst) { | 37 ForwardErrorCorrection::PacketList* dst) { |
36 RTC_DCHECK_GT(n, 0); | 38 RTC_DCHECK_GT(n, 0); |
37 int i = 0; | 39 int i = 0; |
38 for (const auto& packet : src) { | 40 for (const auto& packet : src) { |
39 if (i % n == 0) { | 41 if (i % n == 0) { |
40 dst->emplace_back(new ForwardErrorCorrection::Packet(*packet)); | 42 dst->emplace_back(new ForwardErrorCorrection::Packet(*packet)); |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
144 | 146 |
145 template <typename ForwardErrorCorrectionType> | 147 template <typename ForwardErrorCorrectionType> |
146 bool RtpFecTest<ForwardErrorCorrectionType>::IsRecoveryComplete() { | 148 bool RtpFecTest<ForwardErrorCorrectionType>::IsRecoveryComplete() { |
147 // We must have equally many recovered packets as original packets. | 149 // We must have equally many recovered packets as original packets. |
148 if (recovered_packets_.size() != media_packets_.size()) { | 150 if (recovered_packets_.size() != media_packets_.size()) { |
149 return false; | 151 return false; |
150 } | 152 } |
151 | 153 |
152 // All recovered packets must be identical to the corresponding | 154 // All recovered packets must be identical to the corresponding |
153 // original packets. | 155 // original packets. |
154 using PacketPtr = std::unique_ptr<ForwardErrorCorrection::Packet>; | 156 auto cmp = []( |
155 using RecoveredPacketPtr = | 157 const std::unique_ptr<ForwardErrorCorrection::Packet>& media_packet, |
156 std::unique_ptr<ForwardErrorCorrection::RecoveredPacket>; | 158 const std::unique_ptr<ForwardErrorCorrection::RecoveredPacket>& |
157 auto cmp = [](const PacketPtr& media_packet, | 159 recovered_packet) { |
158 const RecoveredPacketPtr& recovered_packet) { | |
159 if (media_packet->length != recovered_packet->pkt->length) { | 160 if (media_packet->length != recovered_packet->pkt->length) { |
160 return false; | 161 return false; |
161 } | 162 } |
162 if (memcmp(media_packet->data, | 163 if (memcmp(media_packet->data, recovered_packet->pkt->data, |
163 recovered_packet->pkt->data, | |
164 media_packet->length) != 0) { | 164 media_packet->length) != 0) { |
165 return false; | 165 return false; |
166 } | 166 } |
167 return true; | 167 return true; |
168 }; | 168 }; |
169 return std::equal(media_packets_.cbegin(), media_packets_.cend(), | 169 return std::equal(media_packets_.cbegin(), media_packets_.cend(), |
170 recovered_packets_.cbegin(), cmp); | 170 recovered_packets_.cbegin(), cmp); |
171 } | 171 } |
172 | 172 |
173 // Define gTest typed test to loop over both ULPFEC and FlexFEC. | 173 // Define gTest typed test to loop over both ULPFEC and FlexFEC. |
174 // Since the tests now are parameterized, we need to access | 174 // Since the tests now are parameterized, we need to access |
175 // member variables using |this|, thereby enforcing runtime | 175 // member variables using |this|, thereby enforcing runtime |
176 // resolution. | 176 // resolution. |
177 | 177 |
| 178 class FlexfecForwardErrorCorrection : public ForwardErrorCorrection { |
| 179 public: |
| 180 FlexfecForwardErrorCorrection() |
| 181 : ForwardErrorCorrection( |
| 182 std::unique_ptr<FecHeaderReader>(new FlexfecHeaderReader()), |
| 183 std::unique_ptr<FecHeaderWriter>(new FlexfecHeaderWriter())) {} |
| 184 }; |
| 185 |
178 class UlpfecForwardErrorCorrection : public ForwardErrorCorrection { | 186 class UlpfecForwardErrorCorrection : public ForwardErrorCorrection { |
179 public: | 187 public: |
180 UlpfecForwardErrorCorrection() | 188 UlpfecForwardErrorCorrection() |
181 : ForwardErrorCorrection( | 189 : ForwardErrorCorrection( |
182 std::unique_ptr<FecHeaderReader>(new UlpfecHeaderReader()), | 190 std::unique_ptr<FecHeaderReader>(new UlpfecHeaderReader()), |
183 std::unique_ptr<FecHeaderWriter>(new UlpfecHeaderWriter())) {} | 191 std::unique_ptr<FecHeaderWriter>(new UlpfecHeaderWriter())) {} |
184 }; | 192 }; |
185 | 193 |
186 using FecTypes = Types<UlpfecForwardErrorCorrection>; | 194 using FecTypes = |
| 195 Types<FlexfecForwardErrorCorrection, UlpfecForwardErrorCorrection>; |
187 TYPED_TEST_CASE(RtpFecTest, FecTypes); | 196 TYPED_TEST_CASE(RtpFecTest, FecTypes); |
188 | 197 |
189 TYPED_TEST(RtpFecTest, FecRecoveryNoLoss) { | 198 TYPED_TEST(RtpFecTest, FecRecoveryNoLoss) { |
190 constexpr int kNumImportantPackets = 0; | 199 constexpr int kNumImportantPackets = 0; |
191 constexpr bool kUseUnequalProtection = false; | 200 constexpr bool kUseUnequalProtection = false; |
192 constexpr int kNumMediaPackets = 4; | 201 constexpr int kNumMediaPackets = 4; |
193 constexpr uint8_t kProtectionFactor = 60; | 202 constexpr uint8_t kProtectionFactor = 60; |
194 | 203 |
195 this->media_packets_ = | 204 this->media_packets_ = |
196 this->media_packet_generator_.ConstructMediaPackets(kNumMediaPackets); | 205 this->media_packet_generator_.ConstructMediaPackets(kNumMediaPackets); |
(...skipping 745 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
942 this->media_loss_mask_[kNumMediaPackets - 1] = 1; | 951 this->media_loss_mask_[kNumMediaPackets - 1] = 1; |
943 this->NetworkReceivedPackets(this->media_loss_mask_, this->fec_loss_mask_); | 952 this->NetworkReceivedPackets(this->media_loss_mask_, this->fec_loss_mask_); |
944 | 953 |
945 EXPECT_EQ(0, this->fec_.DecodeFec(&this->received_packets_, | 954 EXPECT_EQ(0, this->fec_.DecodeFec(&this->received_packets_, |
946 &this->recovered_packets_)); | 955 &this->recovered_packets_)); |
947 | 956 |
948 // 5 protected packets lost, one FEC packet, cannot get complete recovery. | 957 // 5 protected packets lost, one FEC packet, cannot get complete recovery. |
949 EXPECT_FALSE(this->IsRecoveryComplete()); | 958 EXPECT_FALSE(this->IsRecoveryComplete()); |
950 } | 959 } |
951 | 960 |
| 961 // 'using' directive needed for compiler to be happy. |
| 962 using RtpFecTestWithFlexfec = RtpFecTest<FlexfecForwardErrorCorrection>; |
| 963 TEST_F(RtpFecTestWithFlexfec, |
| 964 FecRecoveryWithLossAndDifferentMediaAndFlexfecSsrcs) { |
| 965 constexpr int kNumImportantPackets = 0; |
| 966 constexpr bool kUseUnequalProtection = false; |
| 967 constexpr int kNumMediaPackets = 4; |
| 968 constexpr uint8_t kProtectionFactor = 60; |
| 969 |
| 970 media_packets_ = |
| 971 media_packet_generator_.ConstructMediaPackets(kNumMediaPackets); |
| 972 |
| 973 EXPECT_EQ(0, fec_.EncodeFec(media_packets_, kProtectionFactor, |
| 974 kNumImportantPackets, kUseUnequalProtection, |
| 975 kFecMaskBursty, &generated_fec_packets_)); |
| 976 |
| 977 // Expect 1 FEC packet. |
| 978 EXPECT_EQ(1u, generated_fec_packets_.size()); |
| 979 |
| 980 // 1 media packet lost |
| 981 memset(media_loss_mask_, 0, sizeof(media_loss_mask_)); |
| 982 memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_)); |
| 983 media_loss_mask_[3] = 1; |
| 984 NetworkReceivedPackets(media_loss_mask_, fec_loss_mask_); |
| 985 |
| 986 // Simulate FlexFEC packet received on different SSRC. |
| 987 auto it = received_packets_.begin(); |
| 988 ++it; |
| 989 ++it; |
| 990 ++it; // Now at the FEC packet. |
| 991 (*it)->ssrc = kFlexfecSsrc; |
| 992 |
| 993 EXPECT_EQ(0, fec_.DecodeFec(&received_packets_, &recovered_packets_)); |
| 994 |
| 995 // One packet lost, one FEC packet, expect complete recovery. |
| 996 EXPECT_TRUE(IsRecoveryComplete()); |
| 997 } |
| 998 |
952 } // namespace webrtc | 999 } // namespace webrtc |
OLD | NEW |