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 "webrtc/modules/rtp_rtcp/source/forward_error_correction.h" | 11 #include "webrtc/modules/rtp_rtcp/source/forward_error_correction.h" |
12 | 12 |
13 #include <string.h> | 13 #include <string.h> |
14 | 14 |
15 #include <algorithm> | 15 #include <algorithm> |
16 #include <iterator> | 16 #include <iterator> |
17 #include <memory> | 17 #include <utility> |
18 | 18 |
19 #include "webrtc/base/checks.h" | 19 #include "webrtc/base/checks.h" |
20 #include "webrtc/base/logging.h" | 20 #include "webrtc/base/logging.h" |
21 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" | 21 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" |
22 #include "webrtc/modules/rtp_rtcp/source/byte_io.h" | 22 #include "webrtc/modules/rtp_rtcp/source/byte_io.h" |
23 #include "webrtc/modules/rtp_rtcp/source/forward_error_correction_internal.h" | 23 #include "webrtc/modules/rtp_rtcp/source/forward_error_correction_internal.h" |
24 | 24 |
25 namespace webrtc { | 25 namespace webrtc { |
26 | 26 |
27 // FEC header size in bytes. | 27 // FEC header size in bytes. |
28 constexpr size_t kFecHeaderSize = 10; | 28 constexpr size_t kFecHeaderSize = 10; |
29 | 29 |
30 // ULP header size in bytes (L bit is set). | 30 // ULP header size in bytes (L bit is set). |
31 constexpr size_t kUlpHeaderSizeLBitSet = (2 + kMaskSizeLBitSet); | 31 constexpr size_t kUlpHeaderSizeLBitSet = (2 + kMaskSizeLBitSet); |
32 | 32 |
33 // ULP header size in bytes (L bit is cleared). | 33 // ULP header size in bytes (L bit is cleared). |
34 constexpr size_t kUlpHeaderSizeLBitClear = (2 + kMaskSizeLBitClear); | 34 constexpr size_t kUlpHeaderSizeLBitClear = (2 + kMaskSizeLBitClear); |
35 | 35 |
36 // Transport header size in bytes. Assume UDP/IPv4 as a reasonable minimum. | 36 // Transport header size in bytes. Assume UDP/IPv4 as a reasonable minimum. |
37 constexpr size_t kTransportOverhead = 28; | 37 constexpr size_t kTransportOverhead = 28; |
38 | 38 |
39 // Maximum number of media packets that can be protected. | |
40 constexpr size_t ForwardErrorCorrection::kMaxMediaPackets; | |
41 | |
39 // Maximum number of FEC packets stored internally. | 42 // Maximum number of FEC packets stored internally. |
40 constexpr size_t kMaxFecPackets = ForwardErrorCorrection::kMaxMediaPackets; | 43 constexpr size_t kMaxFecPackets = ForwardErrorCorrection::kMaxMediaPackets; |
41 | 44 |
42 int32_t ForwardErrorCorrection::Packet::AddRef() { | 45 int32_t ForwardErrorCorrection::Packet::AddRef() { |
43 return ++ref_count_; | 46 return ++ref_count_; |
44 } | 47 } |
45 | 48 |
46 int32_t ForwardErrorCorrection::Packet::Release() { | 49 int32_t ForwardErrorCorrection::Packet::Release() { |
47 int32_t ref_count; | 50 int32_t ref_count; |
48 ref_count = --ref_count_; | 51 ref_count = --ref_count_; |
49 if (ref_count == 0) | 52 if (ref_count == 0) |
50 delete this; | 53 delete this; |
51 return ref_count; | 54 return ref_count; |
52 } | 55 } |
53 | 56 |
54 // Used to link media packets to their protecting FEC packets. | 57 // This comparator is used to compare std::unique_ptr's pointing to |
55 // | 58 // subclasses of SortablePackets. It needs to be parametric since |
56 // TODO(holmer): Refactor into a proper class. | 59 // the std::unique_ptr's are not covariant w.r.t. the types that |
57 class ProtectedPacket : public ForwardErrorCorrection::SortablePacket { | 60 // they are pointing to. |
58 public: | 61 template <typename S, typename T> |
59 rtc::scoped_refptr<ForwardErrorCorrection::Packet> pkt; | 62 bool ForwardErrorCorrection::SortablePacket::LessThan::operator() ( |
60 }; | 63 const S& first, |
61 | 64 const T& second) { |
62 typedef std::list<ProtectedPacket*> ProtectedPacketList; | |
63 | |
64 // | |
65 // Used for internal storage of FEC packets in a list. | |
66 // | |
67 // TODO(holmer): Refactor into a proper class. | |
68 class FecPacket : public ForwardErrorCorrection::SortablePacket { | |
69 public: | |
70 ProtectedPacketList protected_pkt_list; | |
71 uint32_t ssrc; // SSRC of the current frame. | |
72 rtc::scoped_refptr<ForwardErrorCorrection::Packet> pkt; | |
73 }; | |
74 | |
75 bool ForwardErrorCorrection::SortablePacket::LessThan( | |
76 const SortablePacket* first, | |
77 const SortablePacket* second) { | |
78 return IsNewerSequenceNumber(second->seq_num, first->seq_num); | 65 return IsNewerSequenceNumber(second->seq_num, first->seq_num); |
79 } | 66 } |
80 | 67 |
81 ForwardErrorCorrection::ReceivedPacket::ReceivedPacket() {} | 68 ForwardErrorCorrection::ReceivedPacket::ReceivedPacket() {} |
82 ForwardErrorCorrection::ReceivedPacket::~ReceivedPacket() {} | 69 ForwardErrorCorrection::ReceivedPacket::~ReceivedPacket() {} |
83 | 70 |
84 ForwardErrorCorrection::RecoveredPacket::RecoveredPacket() {} | 71 ForwardErrorCorrection::RecoveredPacket::RecoveredPacket() {} |
85 ForwardErrorCorrection::RecoveredPacket::~RecoveredPacket() {} | 72 ForwardErrorCorrection::RecoveredPacket::~RecoveredPacket() {} |
86 | 73 |
87 ForwardErrorCorrection::ForwardErrorCorrection() | 74 ForwardErrorCorrection::ForwardErrorCorrection() |
88 : generated_fec_packets_(kMaxMediaPackets), fec_packet_list_(), | 75 : generated_fec_packets_(kMaxMediaPackets), received_fec_packets_(), |
89 packet_mask_(), tmp_packet_mask_() {} | 76 packet_mask_(), tmp_packet_mask_() {} |
90 ForwardErrorCorrection::~ForwardErrorCorrection() {} | 77 ForwardErrorCorrection::~ForwardErrorCorrection() {} |
91 | 78 |
92 // Input packet | 79 // Input packet |
93 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 80 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
94 // | RTP Header (12 octets) | | 81 // | RTP Header (12 octets) | |
95 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 82 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
96 // | RTP Payload | | 83 // | RTP Payload | |
97 // | | | 84 // | | |
98 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 85 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
99 | 86 |
100 // Output packet | 87 // Output packet |
101 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 88 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
102 // | FEC Header (10 octets) | | 89 // | FEC Header (10 octets) | |
103 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 90 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
104 // | FEC Level 0 Header | | 91 // | FEC Level 0 Header | |
105 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 92 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
106 // | FEC Level 0 Payload | | 93 // | FEC Level 0 Payload | |
107 // | | | 94 // | | |
108 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 95 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
109 // | 96 // |
110 // Note that any potential RED headers are added/removed before calling | 97 // Note that any potential RED headers are added/removed before calling |
111 // GenerateFec() or DecodeFec(). | 98 // GenerateFec() or DecodeFec(). |
112 int ForwardErrorCorrection::GenerateFec(const PacketList& media_packet_list, | 99 int ForwardErrorCorrection::GenerateFec(const PacketList& media_packets, |
113 uint8_t protection_factor, | 100 uint8_t protection_factor, |
114 int num_important_packets, | 101 int num_important_packets, |
115 bool use_unequal_protection, | 102 bool use_unequal_protection, |
116 FecMaskType fec_mask_type, | 103 FecMaskType fec_mask_type, |
117 PacketList* fec_packet_list) { | 104 std::list<Packet*>* fec_packets) { |
118 const uint16_t num_media_packets = media_packet_list.size(); | 105 const uint16_t num_media_packets = media_packets.size(); |
119 // Sanity check arguments. | 106 // Sanity check arguments. |
120 RTC_DCHECK_GT(num_media_packets, 0); | 107 RTC_DCHECK_GT(num_media_packets, 0); |
121 RTC_DCHECK_GE(num_important_packets, 0); | 108 RTC_DCHECK_GE(num_important_packets, 0); |
122 RTC_DCHECK_LE(num_important_packets, num_media_packets); | 109 RTC_DCHECK_LE(num_important_packets, num_media_packets); |
123 RTC_DCHECK(fec_packet_list->empty()); | 110 RTC_DCHECK(fec_packets->empty()); |
124 | 111 |
125 if (num_media_packets > kMaxMediaPackets) { | 112 if (num_media_packets > kMaxMediaPackets) { |
126 LOG(LS_WARNING) << "Can't protect " << num_media_packets | 113 LOG(LS_WARNING) << "Can't protect " << num_media_packets |
127 << " media packets per frame. Max is " << kMaxMediaPackets; | 114 << " media packets per frame. Max is " << kMaxMediaPackets |
115 << "."; | |
128 return -1; | 116 return -1; |
129 } | 117 } |
130 | 118 |
131 bool l_bit = (num_media_packets > 8 * kMaskSizeLBitClear); | 119 bool l_bit = (num_media_packets > 8 * kMaskSizeLBitClear); |
132 int num_mask_bytes = l_bit ? kMaskSizeLBitSet : kMaskSizeLBitClear; | 120 int num_mask_bytes = l_bit ? kMaskSizeLBitSet : kMaskSizeLBitClear; |
133 | 121 |
134 // Do some error checking on the media packets. | 122 // Do some error checking on the media packets. |
135 for (Packet* media_packet : media_packet_list) { | 123 for (const auto& media_packet : media_packets) { |
136 RTC_DCHECK(media_packet); | 124 RTC_DCHECK(media_packet); |
137 | 125 |
138 if (media_packet->length < kRtpHeaderSize) { | 126 if (media_packet->length < kRtpHeaderSize) { |
139 LOG(LS_WARNING) << "Media packet " << media_packet->length << " bytes " | 127 LOG(LS_WARNING) << "Media packet " << media_packet->length << " bytes " |
140 << "is smaller than RTP header."; | 128 << "is smaller than RTP header."; |
141 return -1; | 129 return -1; |
142 } | 130 } |
143 | 131 |
144 // Ensure our FEC packets will fit in a typical MTU. | 132 // Ensure our FEC packets will fit in a typical MTU. |
145 if (media_packet->length + PacketOverhead() + kTransportOverhead > | 133 if (media_packet->length + PacketOverhead() + kTransportOverhead > |
146 IP_PACKET_SIZE) { | 134 IP_PACKET_SIZE) { |
147 LOG(LS_WARNING) << "Media packet " << media_packet->length << " bytes " | 135 LOG(LS_WARNING) << "Media packet " << media_packet->length << " bytes " |
148 << "with overhead is larger than " << IP_PACKET_SIZE; | 136 << "with overhead is larger than " << IP_PACKET_SIZE |
137 << " bytes."; | |
149 } | 138 } |
150 } | 139 } |
151 | 140 |
152 int num_fec_packets = | 141 int num_fec_packets = |
153 GetNumberOfFecPackets(num_media_packets, protection_factor); | 142 GetNumberOfFecPackets(num_media_packets, protection_factor); |
154 if (num_fec_packets == 0) { | 143 if (num_fec_packets == 0) { |
155 return 0; | 144 return 0; |
156 } | 145 } |
157 | 146 |
158 // Prepare FEC packets by setting them to 0. | 147 // Prepare generated FEC packets by setting them to 0. |
159 for (int i = 0; i < num_fec_packets; ++i) { | 148 for (int i = 0; i < num_fec_packets; ++i) { |
160 memset(generated_fec_packets_[i].data, 0, IP_PACKET_SIZE); | 149 memset(generated_fec_packets_[i].data, 0, IP_PACKET_SIZE); |
161 generated_fec_packets_[i].length = 0; // Use this as a marker for untouched | 150 // Use this as a marker for untouched packets. |
162 // packets. | 151 generated_fec_packets_[i].length = 0; |
163 fec_packet_list->push_back(&generated_fec_packets_[i]); | 152 fec_packets->push_back(&generated_fec_packets_[i]); |
164 } | 153 } |
165 | 154 |
166 const internal::PacketMaskTable mask_table(fec_mask_type, num_media_packets); | 155 const internal::PacketMaskTable mask_table(fec_mask_type, num_media_packets); |
167 | 156 |
168 // -- Generate packet masks -- | 157 // -- Generate packet masks -- |
169 memset(packet_mask_, 0, num_fec_packets * num_mask_bytes); | 158 memset(packet_mask_, 0, num_fec_packets * num_mask_bytes); |
170 internal::GeneratePacketMasks(num_media_packets, num_fec_packets, | 159 internal::GeneratePacketMasks(num_media_packets, num_fec_packets, |
171 num_important_packets, use_unequal_protection, | 160 num_important_packets, use_unequal_protection, |
172 mask_table, packet_mask_); | 161 mask_table, packet_mask_); |
173 | 162 |
174 int num_mask_bits = InsertZerosInBitMasks( | 163 int num_mask_bits = InsertZerosInBitMasks( |
175 media_packet_list, packet_mask_, num_mask_bytes, num_fec_packets); | 164 media_packets, packet_mask_, num_mask_bytes, num_fec_packets); |
176 | 165 |
177 if (num_mask_bits < 0) { | 166 if (num_mask_bits < 0) { |
178 return -1; | 167 return -1; |
179 } | 168 } |
180 l_bit = (static_cast<size_t>(num_mask_bits) > 8 * kMaskSizeLBitClear); | 169 l_bit = (static_cast<size_t>(num_mask_bits) > 8 * kMaskSizeLBitClear); |
181 if (l_bit) { | 170 if (l_bit) { |
182 num_mask_bytes = kMaskSizeLBitSet; | 171 num_mask_bytes = kMaskSizeLBitSet; |
183 } | 172 } |
184 | 173 |
185 GenerateFecBitStrings(media_packet_list, packet_mask_, | 174 GenerateFecBitStrings(media_packets, packet_mask_, num_fec_packets, l_bit); |
186 num_fec_packets, l_bit); | 175 GenerateFecUlpHeaders(media_packets, packet_mask_, num_fec_packets, l_bit); |
187 GenerateFecUlpHeaders(media_packet_list, packet_mask_, | |
188 num_fec_packets, l_bit); | |
189 | 176 |
190 return 0; | 177 return 0; |
191 } | 178 } |
192 | 179 |
193 int ForwardErrorCorrection::GetNumberOfFecPackets(int num_media_packets, | 180 int ForwardErrorCorrection::GetNumberOfFecPackets(int num_media_packets, |
194 int protection_factor) { | 181 int protection_factor) { |
195 // Result in Q0 with an unsigned round. | 182 // Result in Q0 with an unsigned round. |
196 int num_fec_packets = (num_media_packets * protection_factor + (1 << 7)) >> 8; | 183 int num_fec_packets = (num_media_packets * protection_factor + (1 << 7)) >> 8; |
197 // Generate at least one FEC packet if we need protection. | 184 // Generate at least one FEC packet if we need protection. |
198 if (protection_factor > 0 && num_fec_packets == 0) { | 185 if (protection_factor > 0 && num_fec_packets == 0) { |
199 num_fec_packets = 1; | 186 num_fec_packets = 1; |
200 } | 187 } |
201 RTC_DCHECK_LE(num_fec_packets, num_media_packets); | 188 RTC_DCHECK_LE(num_fec_packets, num_media_packets); |
202 return num_fec_packets; | 189 return num_fec_packets; |
203 } | 190 } |
204 | 191 |
205 void ForwardErrorCorrection::GenerateFecBitStrings( | 192 void ForwardErrorCorrection::GenerateFecBitStrings( |
206 const PacketList& media_packet_list, | 193 const PacketList& media_packets, |
207 uint8_t* packet_mask, | 194 uint8_t* packet_mask, |
208 int num_fec_packets, | 195 int num_fec_packets, |
209 bool l_bit) { | 196 bool l_bit) { |
210 RTC_DCHECK(!media_packet_list.empty()); | 197 RTC_DCHECK(!media_packets.empty()); |
211 uint8_t media_payload_length[2]; | 198 uint8_t media_payload_length[2]; |
212 const int num_mask_bytes = l_bit ? kMaskSizeLBitSet : kMaskSizeLBitClear; | 199 const int num_mask_bytes = l_bit ? kMaskSizeLBitSet : kMaskSizeLBitClear; |
213 const uint16_t ulp_header_size = | 200 const uint16_t ulp_header_size = |
214 l_bit ? kUlpHeaderSizeLBitSet : kUlpHeaderSizeLBitClear; | 201 l_bit ? kUlpHeaderSizeLBitSet : kUlpHeaderSizeLBitClear; |
215 const uint16_t fec_rtp_offset = | 202 const uint16_t fec_rtp_offset = |
216 kFecHeaderSize + ulp_header_size - kRtpHeaderSize; | 203 kFecHeaderSize + ulp_header_size - kRtpHeaderSize; |
217 | 204 |
218 for (int i = 0; i < num_fec_packets; ++i) { | 205 for (int i = 0; i < num_fec_packets; ++i) { |
219 Packet* const fec_packet = &generated_fec_packets_[i]; | 206 Packet* const fec_packet = &generated_fec_packets_[i]; |
220 auto media_list_it = media_packet_list.cbegin(); | 207 auto media_packets_it = media_packets.cbegin(); |
221 uint32_t pkt_mask_idx = i * num_mask_bytes; | 208 uint32_t pkt_mask_idx = i * num_mask_bytes; |
222 uint32_t media_pkt_idx = 0; | 209 uint32_t media_pkt_idx = 0; |
223 uint16_t fec_packet_length = 0; | 210 uint16_t fec_packet_length = 0; |
224 uint16_t prev_seq_num = ParseSequenceNumber((*media_list_it)->data); | 211 uint16_t prev_seq_num = ParseSequenceNumber((*media_packets_it)->data); |
225 while (media_list_it != media_packet_list.end()) { | 212 while (media_packets_it != media_packets.end()) { |
226 // Each FEC packet has a multiple byte mask. Determine if this media | 213 // Each FEC packet has a multiple byte mask. Determine if this media |
227 // packet should be included in FEC packet i. | 214 // packet should be included in FEC packet i. |
228 if (packet_mask[pkt_mask_idx] & (1 << (7 - media_pkt_idx))) { | 215 if (packet_mask[pkt_mask_idx] & (1 << (7 - media_pkt_idx))) { |
229 Packet* media_packet = *media_list_it; | 216 Packet* media_packet = media_packets_it->get(); |
230 | 217 |
231 // Assign network-ordered media payload length. | 218 // Assign network-ordered media payload length. |
232 ByteWriter<uint16_t>::WriteBigEndian( | 219 ByteWriter<uint16_t>::WriteBigEndian( |
233 media_payload_length, media_packet->length - kRtpHeaderSize); | 220 media_payload_length, media_packet->length - kRtpHeaderSize); |
234 | 221 |
235 fec_packet_length = media_packet->length + fec_rtp_offset; | 222 fec_packet_length = media_packet->length + fec_rtp_offset; |
236 // On the first protected packet, we don't need to XOR. | 223 // On the first protected packet, we don't need to XOR. |
237 if (fec_packet->length == 0) { | 224 if (fec_packet->length == 0) { |
238 // Copy the first 2 bytes of the RTP header. Note that the E and L | 225 // Copy the first 2 bytes of the RTP header. Note that the E and L |
239 // bits are overwritten in GenerateFecUlpHeaders. | 226 // bits are overwritten in GenerateFecUlpHeaders. |
(...skipping 24 matching lines...) Expand all Loading... | |
264 // XOR with RTP payload, leaving room for the ULP header. | 251 // XOR with RTP payload, leaving room for the ULP header. |
265 for (int32_t j = kFecHeaderSize + ulp_header_size; | 252 for (int32_t j = kFecHeaderSize + ulp_header_size; |
266 j < fec_packet_length; j++) { | 253 j < fec_packet_length; j++) { |
267 fec_packet->data[j] ^= media_packet->data[j - fec_rtp_offset]; | 254 fec_packet->data[j] ^= media_packet->data[j - fec_rtp_offset]; |
268 } | 255 } |
269 } | 256 } |
270 if (fec_packet_length > fec_packet->length) { | 257 if (fec_packet_length > fec_packet->length) { |
271 fec_packet->length = fec_packet_length; | 258 fec_packet->length = fec_packet_length; |
272 } | 259 } |
273 } | 260 } |
274 media_list_it++; | 261 media_packets_it++; |
275 if (media_list_it != media_packet_list.end()) { | 262 if (media_packets_it != media_packets.end()) { |
276 uint16_t seq_num = ParseSequenceNumber((*media_list_it)->data); | 263 uint16_t seq_num = ParseSequenceNumber((*media_packets_it)->data); |
277 media_pkt_idx += static_cast<uint16_t>(seq_num - prev_seq_num); | 264 media_pkt_idx += static_cast<uint16_t>(seq_num - prev_seq_num); |
278 prev_seq_num = seq_num; | 265 prev_seq_num = seq_num; |
279 } | 266 } |
280 pkt_mask_idx += media_pkt_idx / 8; | 267 pkt_mask_idx += media_pkt_idx / 8; |
281 media_pkt_idx %= 8; | 268 media_pkt_idx %= 8; |
282 } | 269 } |
283 RTC_DCHECK_GT(fec_packet->length, 0u) | 270 RTC_DCHECK_GT(fec_packet->length, 0u) |
284 << "Packet mask is wrong or poorly designed."; | 271 << "Packet mask is wrong or poorly designed."; |
285 } | 272 } |
286 } | 273 } |
(...skipping 14 matching lines...) Expand all Loading... | |
301 if (total_missing_seq_nums == 0) { | 288 if (total_missing_seq_nums == 0) { |
302 // All sequence numbers are covered by the packet mask. No zero insertion | 289 // All sequence numbers are covered by the packet mask. No zero insertion |
303 // required. | 290 // required. |
304 return media_packets.size(); | 291 return media_packets.size(); |
305 } | 292 } |
306 // We can only protect 8 * kMaskSizeLBitSet packets. | 293 // We can only protect 8 * kMaskSizeLBitSet packets. |
307 if (total_missing_seq_nums + media_packets.size() > 8 * kMaskSizeLBitSet) | 294 if (total_missing_seq_nums + media_packets.size() > 8 * kMaskSizeLBitSet) |
308 return -1; | 295 return -1; |
309 // Allocate the new mask. | 296 // Allocate the new mask. |
310 int new_mask_bytes = kMaskSizeLBitClear; | 297 int new_mask_bytes = kMaskSizeLBitClear; |
311 if (media_packets.size() + total_missing_seq_nums > 8 * kMaskSizeLBitClear) { | 298 if (media_packets.size() + |
299 total_missing_seq_nums > 8 * kMaskSizeLBitClear) { | |
312 new_mask_bytes = kMaskSizeLBitSet; | 300 new_mask_bytes = kMaskSizeLBitSet; |
313 } | 301 } |
314 memset(tmp_packet_mask_, 0, num_fec_packets * kMaskSizeLBitSet); | 302 memset(tmp_packet_mask_, 0, num_fec_packets * kMaskSizeLBitSet); |
315 | 303 |
316 auto it = media_packets.cbegin(); | 304 auto media_packets_it = media_packets.cbegin(); |
317 uint16_t prev_seq_num = first_seq_num; | 305 uint16_t prev_seq_num = first_seq_num; |
318 ++it; | 306 ++media_packets_it; |
319 | 307 |
320 // Insert the first column. | 308 // Insert the first column. |
321 CopyColumn(tmp_packet_mask_, new_mask_bytes, packet_mask, num_mask_bytes, | 309 CopyColumn(tmp_packet_mask_, new_mask_bytes, packet_mask, num_mask_bytes, |
322 num_fec_packets, 0, 0); | 310 num_fec_packets, 0, 0); |
323 int new_bit_index = 1; | 311 int new_bit_index = 1; |
324 int old_bit_index = 1; | 312 int old_bit_index = 1; |
325 // Insert zeros in the bit mask for every hole in the sequence. | 313 // Insert zeros in the bit mask for every hole in the sequence. |
326 for (; it != media_packets.end(); ++it) { | 314 while (media_packets_it != media_packets.end()) { |
327 if (new_bit_index == 8 * kMaskSizeLBitSet) { | 315 if (new_bit_index == 8 * kMaskSizeLBitSet) { |
328 // We can only cover up to 48 packets. | 316 // We can only cover up to 48 packets. |
329 break; | 317 break; |
330 } | 318 } |
331 uint16_t seq_num = ParseSequenceNumber((*it)->data); | 319 uint16_t seq_num = ParseSequenceNumber((*media_packets_it)->data); |
332 const int zeros_to_insert = | 320 const int zeros_to_insert = |
333 static_cast<uint16_t>(seq_num - prev_seq_num - 1); | 321 static_cast<uint16_t>(seq_num - prev_seq_num - 1); |
334 if (zeros_to_insert > 0) { | 322 if (zeros_to_insert > 0) { |
335 InsertZeroColumns(zeros_to_insert, tmp_packet_mask_, new_mask_bytes, | 323 InsertZeroColumns(zeros_to_insert, tmp_packet_mask_, new_mask_bytes, |
336 num_fec_packets, new_bit_index); | 324 num_fec_packets, new_bit_index); |
337 } | 325 } |
338 new_bit_index += zeros_to_insert; | 326 new_bit_index += zeros_to_insert; |
339 CopyColumn(tmp_packet_mask_, new_mask_bytes, packet_mask, num_mask_bytes, | 327 CopyColumn(tmp_packet_mask_, new_mask_bytes, packet_mask, num_mask_bytes, |
340 num_fec_packets, new_bit_index, old_bit_index); | 328 num_fec_packets, new_bit_index, old_bit_index); |
341 ++new_bit_index; | 329 ++new_bit_index; |
342 ++old_bit_index; | 330 ++old_bit_index; |
343 prev_seq_num = seq_num; | 331 prev_seq_num = seq_num; |
332 ++media_packets_it; | |
344 } | 333 } |
345 if (new_bit_index % 8 != 0) { | 334 if (new_bit_index % 8 != 0) { |
346 // We didn't fill the last byte. Shift bits to correct position. | 335 // We didn't fill the last byte. Shift bits to correct position. |
347 for (uint16_t row = 0; row < num_fec_packets; ++row) { | 336 for (uint16_t row = 0; row < num_fec_packets; ++row) { |
348 int new_byte_index = row * new_mask_bytes + new_bit_index / 8; | 337 int new_byte_index = row * new_mask_bytes + new_bit_index / 8; |
349 tmp_packet_mask_[new_byte_index] <<= (7 - (new_bit_index % 8)); | 338 tmp_packet_mask_[new_byte_index] <<= (7 - (new_bit_index % 8)); |
350 } | 339 } |
351 } | 340 } |
352 // Replace the old mask with the new. | 341 // Replace the old mask with the new. |
353 memcpy(packet_mask, tmp_packet_mask_, kMaskSizeLBitSet * num_fec_packets); | 342 memcpy(packet_mask, tmp_packet_mask_, kMaskSizeLBitSet * num_fec_packets); |
(...skipping 26 matching lines...) Expand all Loading... | |
380 int old_byte_index = row * old_mask_bytes + old_bit_index / 8; | 369 int old_byte_index = row * old_mask_bytes + old_bit_index / 8; |
381 new_mask[new_byte_index] |= ((old_mask[old_byte_index] & 0x80) >> 7); | 370 new_mask[new_byte_index] |= ((old_mask[old_byte_index] & 0x80) >> 7); |
382 if (new_bit_index % 8 != 7) { | 371 if (new_bit_index % 8 != 7) { |
383 new_mask[new_byte_index] <<= 1; | 372 new_mask[new_byte_index] <<= 1; |
384 } | 373 } |
385 old_mask[old_byte_index] <<= 1; | 374 old_mask[old_byte_index] <<= 1; |
386 } | 375 } |
387 } | 376 } |
388 | 377 |
389 void ForwardErrorCorrection::GenerateFecUlpHeaders( | 378 void ForwardErrorCorrection::GenerateFecUlpHeaders( |
390 const PacketList& media_packet_list, | 379 const PacketList& media_packets, |
391 uint8_t* packet_mask, | 380 uint8_t* packet_mask, |
392 int num_fec_packets, | 381 int num_fec_packets, |
393 bool l_bit) { | 382 bool l_bit) { |
394 // -- Generate FEC and ULP headers -- | 383 // -- Generate FEC and ULP headers -- |
395 // | 384 // |
396 // FEC Header, 10 bytes | 385 // FEC Header, 10 bytes |
397 // 0 1 2 3 | 386 // 0 1 2 3 |
398 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 | 387 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 |
399 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 388 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
400 // |E|L|P|X| CC |M| PT recovery | SN base | | 389 // |E|L|P|X| CC |M| PT recovery | SN base | |
401 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 390 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
402 // | TS recovery | | 391 // | TS recovery | |
403 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 392 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
404 // | length recovery | | 393 // | length recovery | |
405 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 394 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
406 // | 395 // |
407 // ULP Header, 4 bytes (for L = 0) | 396 // ULP Header, 4 bytes (for L = 0) |
408 // 0 1 2 3 | 397 // 0 1 2 3 |
409 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 | 398 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 |
410 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 399 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
411 // | Protection Length | mask | | 400 // | Protection Length | mask | |
412 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 401 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
413 // | mask cont. (present only when L = 1) | | 402 // | mask cont. (present only when L = 1) | |
414 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 403 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
415 int num_mask_bytes = l_bit ? kMaskSizeLBitSet : kMaskSizeLBitClear; | 404 int num_mask_bytes = l_bit ? kMaskSizeLBitSet : kMaskSizeLBitClear; |
416 const uint16_t ulp_header_size = | 405 const uint16_t ulp_header_size = |
417 l_bit ? kUlpHeaderSizeLBitSet : kUlpHeaderSizeLBitClear; | 406 l_bit ? kUlpHeaderSizeLBitSet : kUlpHeaderSizeLBitClear; |
418 | 407 |
419 RTC_DCHECK(!media_packet_list.empty()); | 408 RTC_DCHECK(!media_packets.empty()); |
420 Packet* first_media_packet = media_packet_list.front(); | 409 Packet* first_media_packet = media_packets.front().get(); |
421 RTC_DCHECK(first_media_packet); | 410 RTC_DCHECK(first_media_packet); |
422 uint16_t seq_num = ParseSequenceNumber(first_media_packet->data); | 411 uint16_t seq_num = ParseSequenceNumber(first_media_packet->data); |
423 for (int i = 0; i < num_fec_packets; ++i) { | 412 for (int i = 0; i < num_fec_packets; ++i) { |
424 Packet* const fec_packet = &generated_fec_packets_[i]; | 413 Packet* const fec_packet = &generated_fec_packets_[i]; |
425 // -- FEC header -- | 414 // -- FEC header -- |
426 fec_packet->data[0] &= 0x7f; // Set E to zero. | 415 fec_packet->data[0] &= 0x7f; // Set E to zero. |
427 if (l_bit == 0) { | 416 if (l_bit == 0) { |
428 fec_packet->data[0] &= 0xbf; // Clear the L bit. | 417 fec_packet->data[0] &= 0xbf; // Clear the L bit. |
429 } else { | 418 } else { |
430 fec_packet->data[0] |= 0x40; // Set the L bit. | 419 fec_packet->data[0] |= 0x40; // Set the L bit. |
(...skipping 10 matching lines...) Expand all Loading... | |
441 &fec_packet->data[10], | 430 &fec_packet->data[10], |
442 fec_packet->length - kFecHeaderSize - ulp_header_size); | 431 fec_packet->length - kFecHeaderSize - ulp_header_size); |
443 | 432 |
444 // Copy the packet mask. | 433 // Copy the packet mask. |
445 memcpy(&fec_packet->data[12], &packet_mask[i * num_mask_bytes], | 434 memcpy(&fec_packet->data[12], &packet_mask[i * num_mask_bytes], |
446 num_mask_bytes); | 435 num_mask_bytes); |
447 } | 436 } |
448 } | 437 } |
449 | 438 |
450 void ForwardErrorCorrection::ResetState( | 439 void ForwardErrorCorrection::ResetState( |
451 RecoveredPacketList* recovered_packet_list) { | 440 RecoveredPacketList* recovered_packets) { |
452 // Free the memory for any existing recovered packets, if the user hasn't. | 441 // Free the memory for any existing recovered packets, if the user hasn't. |
453 while (!recovered_packet_list->empty()) { | 442 recovered_packets->clear(); |
454 delete recovered_packet_list->front(); | 443 received_fec_packets_.clear(); |
455 recovered_packet_list->pop_front(); | |
456 } | |
457 RTC_DCHECK(recovered_packet_list->empty()); | |
458 | |
459 // Free the FEC packet list. | |
460 while (!fec_packet_list_.empty()) { | |
461 FecPacket* fec_packet = fec_packet_list_.front(); | |
462 auto protected_packet_list_it = fec_packet->protected_pkt_list.begin(); | |
463 while (protected_packet_list_it != fec_packet->protected_pkt_list.end()) { | |
464 delete *protected_packet_list_it; | |
465 protected_packet_list_it = | |
466 fec_packet->protected_pkt_list.erase(protected_packet_list_it); | |
467 } | |
468 RTC_DCHECK(fec_packet->protected_pkt_list.empty()); | |
469 delete fec_packet; | |
470 fec_packet_list_.pop_front(); | |
471 } | |
472 RTC_DCHECK(fec_packet_list_.empty()); | |
473 } | 444 } |
474 | 445 |
475 void ForwardErrorCorrection::InsertMediaPacket( | 446 void ForwardErrorCorrection::InsertMediaPacket( |
476 ReceivedPacket* rx_packet, | 447 ReceivedPacket* rx_packet, |
477 RecoveredPacketList* recovered_packet_list) { | 448 RecoveredPacketList* recovered_packets) { |
478 auto recovered_packet_list_it = recovered_packet_list->cbegin(); | |
479 | 449 |
480 // Search for duplicate packets. | 450 // Search for duplicate packets. |
481 while (recovered_packet_list_it != recovered_packet_list->end()) { | 451 for (const auto& recovered_packet : *recovered_packets) { |
482 if (rx_packet->seq_num == (*recovered_packet_list_it)->seq_num) { | 452 if (rx_packet->seq_num == recovered_packet->seq_num) { |
483 // Duplicate packet, no need to add to list. | 453 // Duplicate packet, no need to add to list. |
484 // Delete duplicate media packet data. | 454 // Delete duplicate media packet data. |
485 rx_packet->pkt = nullptr; | 455 rx_packet->pkt = nullptr; |
486 return; | 456 return; |
487 } | 457 } |
488 ++recovered_packet_list_it; | |
489 } | 458 } |
490 RecoveredPacket* recovered_packet_to_insert = new RecoveredPacket(); | 459 std::unique_ptr<RecoveredPacket> recovered_packet_to_insert( |
460 new RecoveredPacket()); | |
461 // This "recovered packet" was not recovered using parity packets. | |
491 recovered_packet_to_insert->was_recovered = false; | 462 recovered_packet_to_insert->was_recovered = false; |
492 // Inserted Media packet is already sent to VCM. | 463 // This media packet has already been passed on. |
493 recovered_packet_to_insert->returned = true; | 464 recovered_packet_to_insert->returned = true; |
494 recovered_packet_to_insert->seq_num = rx_packet->seq_num; | 465 recovered_packet_to_insert->seq_num = rx_packet->seq_num; |
495 recovered_packet_to_insert->pkt = rx_packet->pkt; | 466 recovered_packet_to_insert->pkt = rx_packet->pkt; |
496 recovered_packet_to_insert->pkt->length = rx_packet->pkt->length; | 467 recovered_packet_to_insert->pkt->length = rx_packet->pkt->length; |
497 | 468 |
469 RecoveredPacket* recovered_packet_to_insert_ptr = | |
470 recovered_packet_to_insert.get(); | |
498 // TODO(holmer): Consider replacing this with a binary search for the right | 471 // TODO(holmer): Consider replacing this with a binary search for the right |
499 // position, and then just insert the new packet. Would get rid of the sort. | 472 // position, and then just insert the new packet. Would get rid of the sort. |
500 recovered_packet_list->push_back(recovered_packet_to_insert); | 473 recovered_packets->push_back(std::move(recovered_packet_to_insert)); |
501 recovered_packet_list->sort(SortablePacket::LessThan); | 474 recovered_packets->sort(SortablePacket::LessThan()); |
danilchap
2016/08/01 14:39:24
here SortablePacket::LessThan has to be a functor.
| |
502 UpdateCoveringFecPackets(recovered_packet_to_insert); | 475 UpdateCoveringFecPackets(recovered_packet_to_insert_ptr); |
503 } | 476 } |
504 | 477 |
505 void ForwardErrorCorrection::UpdateCoveringFecPackets(RecoveredPacket* packet) { | 478 void ForwardErrorCorrection::UpdateCoveringFecPackets(RecoveredPacket* packet) { |
506 for (auto* fec_packet : fec_packet_list_) { | 479 for (auto& fec_packet : received_fec_packets_) { |
507 // Is this FEC packet protecting the media packet |packet|? | 480 // Is this FEC packet protecting the media packet |packet|? |
508 auto protected_it = std::lower_bound(fec_packet->protected_pkt_list.begin(), | 481 auto protected_it = std::lower_bound(fec_packet->protected_pkt_list.begin(), |
509 fec_packet->protected_pkt_list.end(), | 482 fec_packet->protected_pkt_list.end(), |
510 packet, | 483 packet, |
511 SortablePacket::LessThan); | 484 SortablePacket::LessThan()); |
512 if (protected_it != fec_packet->protected_pkt_list.end() && | 485 if (protected_it != fec_packet->protected_pkt_list.end() && |
513 (*protected_it)->seq_num == packet->seq_num) { | 486 (*protected_it)->seq_num == packet->seq_num) { |
514 // Found an FEC packet which is protecting |packet|. | 487 // Found an FEC packet which is protecting |packet|. |
515 (*protected_it)->pkt = packet->pkt; | 488 (*protected_it)->pkt = packet->pkt; |
516 } | 489 } |
517 } | 490 } |
518 } | 491 } |
519 | 492 |
520 void ForwardErrorCorrection::InsertFecPacket( | 493 void ForwardErrorCorrection::InsertFecPacket( |
521 ReceivedPacket* rx_packet, | 494 ReceivedPacket* rx_packet, |
522 const RecoveredPacketList* recovered_packet_list) { | 495 const RecoveredPacketList* recovered_packets) { |
523 // Check for duplicate. | 496 // Check for duplicate. |
524 for (auto* fec_packet : fec_packet_list_) { | 497 for (const auto& existing_fec_packet : received_fec_packets_) { |
525 if (rx_packet->seq_num == fec_packet->seq_num) { | 498 if (rx_packet->seq_num == existing_fec_packet->seq_num) { |
526 // Delete duplicate FEC packet data. | 499 // Delete duplicate FEC packet data. |
527 rx_packet->pkt = nullptr; | 500 rx_packet->pkt = nullptr; |
528 return; | 501 return; |
529 } | 502 } |
530 } | 503 } |
531 FecPacket* fec_packet = new FecPacket(); | 504 std::unique_ptr<ReceivedFecPacket> fec_packet(new ReceivedFecPacket()); |
532 fec_packet->pkt = rx_packet->pkt; | 505 fec_packet->pkt = rx_packet->pkt; |
533 fec_packet->seq_num = rx_packet->seq_num; | 506 fec_packet->seq_num = rx_packet->seq_num; |
534 fec_packet->ssrc = rx_packet->ssrc; | 507 fec_packet->ssrc = rx_packet->ssrc; |
535 | 508 |
536 const uint16_t seq_num_base = | 509 const uint16_t seq_num_base = |
537 ByteReader<uint16_t>::ReadBigEndian(&fec_packet->pkt->data[2]); | 510 ByteReader<uint16_t>::ReadBigEndian(&fec_packet->pkt->data[2]); |
538 const uint16_t maskSizeBytes = (fec_packet->pkt->data[0] & 0x40) | 511 const uint16_t maskSizeBytes = (fec_packet->pkt->data[0] & 0x40) |
539 ? kMaskSizeLBitSet | 512 ? kMaskSizeLBitSet |
540 : kMaskSizeLBitClear; // L bit set? | 513 : kMaskSizeLBitClear; // L bit set? |
541 | 514 |
542 for (uint16_t byte_idx = 0; byte_idx < maskSizeBytes; ++byte_idx) { | 515 for (uint16_t byte_idx = 0; byte_idx < maskSizeBytes; ++byte_idx) { |
543 uint8_t packet_mask = fec_packet->pkt->data[12 + byte_idx]; | 516 uint8_t packet_mask = fec_packet->pkt->data[12 + byte_idx]; |
544 for (uint16_t bit_idx = 0; bit_idx < 8; ++bit_idx) { | 517 for (uint16_t bit_idx = 0; bit_idx < 8; ++bit_idx) { |
545 if (packet_mask & (1 << (7 - bit_idx))) { | 518 if (packet_mask & (1 << (7 - bit_idx))) { |
546 ProtectedPacket* protected_packet = new ProtectedPacket(); | 519 std::unique_ptr<ProtectedPacket> protected_packet( |
547 fec_packet->protected_pkt_list.push_back(protected_packet); | 520 new ProtectedPacket()); |
548 // This wraps naturally with the sequence number. | 521 // This wraps naturally with the sequence number. |
549 protected_packet->seq_num = | 522 protected_packet->seq_num = |
550 static_cast<uint16_t>(seq_num_base + (byte_idx << 3) + bit_idx); | 523 static_cast<uint16_t>(seq_num_base + (byte_idx << 3) + bit_idx); |
551 protected_packet->pkt = nullptr; | 524 protected_packet->pkt = nullptr; |
525 fec_packet->protected_pkt_list.push_back(std::move(protected_packet)); | |
552 } | 526 } |
553 } | 527 } |
554 } | 528 } |
555 if (fec_packet->protected_pkt_list.empty()) { | 529 if (fec_packet->protected_pkt_list.empty()) { |
556 // All-zero packet mask; we can discard this FEC packet. | 530 // All-zero packet mask; we can discard this FEC packet. |
557 LOG(LS_WARNING) << "FEC packet has an all-zero packet mask."; | 531 LOG(LS_WARNING) << "FEC packet has an all-zero packet mask."; |
558 delete fec_packet; | |
559 } else { | 532 } else { |
560 AssignRecoveredPackets(fec_packet, recovered_packet_list); | 533 AssignRecoveredPackets(fec_packet.get(), recovered_packets); |
561 // TODO(holmer): Consider replacing this with a binary search for the right | 534 // TODO(holmer): Consider replacing this with a binary search for the right |
562 // position, and then just insert the new packet. Would get rid of the sort. | 535 // position, and then just insert the new packet. Would get rid of the sort. |
563 fec_packet_list_.push_back(fec_packet); | 536 received_fec_packets_.push_back(std::move(fec_packet)); |
564 fec_packet_list_.sort(SortablePacket::LessThan); | 537 received_fec_packets_.sort(SortablePacket::LessThan()); |
565 if (fec_packet_list_.size() > kMaxFecPackets) { | 538 if (received_fec_packets_.size() > kMaxFecPackets) { |
566 DiscardFecPacket(fec_packet_list_.front()); | 539 received_fec_packets_.pop_front(); |
567 fec_packet_list_.pop_front(); | |
568 } | 540 } |
569 RTC_DCHECK_LE(fec_packet_list_.size(), kMaxFecPackets); | 541 RTC_DCHECK_LE(received_fec_packets_.size(), kMaxFecPackets); |
570 } | 542 } |
571 } | 543 } |
572 | 544 |
573 void ForwardErrorCorrection::AssignRecoveredPackets( | 545 void ForwardErrorCorrection::AssignRecoveredPackets( |
574 FecPacket* fec_packet, | 546 ReceivedFecPacket* fec_packet, |
575 const RecoveredPacketList* recovered_packets) { | 547 const RecoveredPacketList* recovered_packets) { |
576 // Search for missing packets which have arrived or have been recovered by | 548 ProtectedPacketList* protected_packets = &fec_packet->protected_pkt_list; |
577 // another FEC packet. | 549 std::vector<RecoveredPacket*> recovered_protected_packets; |
578 ProtectedPacketList* not_recovered = &fec_packet->protected_pkt_list; | 550 |
579 RecoveredPacketList already_recovered; | 551 // Find intersection between the (sorted) containers |protected_packets| |
580 std::set_intersection( | 552 // and |recovered_packets|, i.e. all protected packets that have already |
581 recovered_packets->cbegin(), recovered_packets->cend(), | 553 // been recovered. Update the corresponding protected packets to point to |
582 not_recovered->cbegin(), not_recovered->cend(), | 554 // the recovered packets. |
583 std::inserter(already_recovered, already_recovered.end()), | 555 auto it_p = protected_packets->cbegin(); |
584 SortablePacket::LessThan); | 556 auto it_r = recovered_packets->cbegin(); |
585 // Set the FEC pointers to all recovered packets so that we don't have to | 557 SortablePacket::LessThan less_than; |
stefan-webrtc
2016/08/01 11:29:51
I might be mistaking myself, but if the function w
| |
586 // search for them when we are doing recovery. | 558 while (it_p != protected_packets->end() && it_r != recovered_packets->end()) { |
587 auto not_recovered_it = not_recovered->cbegin(); | 559 if (less_than(*it_p, *it_r)) { |
588 for (auto it = already_recovered.cbegin(); | 560 ++it_p; |
589 it != already_recovered.end(); ++it) { | 561 } else if (less_than(*it_r, *it_p)) { |
590 // Search for the next recovered packet in |not_recovered|. | 562 ++it_r; |
591 while ((*not_recovered_it)->seq_num != (*it)->seq_num) | 563 } else { // *it_p == *it_r. |
592 ++not_recovered_it; | 564 // This protected packet has already been recovered. |
593 (*not_recovered_it)->pkt = (*it)->pkt; | 565 (*it_p)->pkt = (*it_r)->pkt; |
566 ++it_p; | |
567 ++it_r; | |
568 } | |
594 } | 569 } |
595 } | 570 } |
596 | 571 |
597 void ForwardErrorCorrection::InsertPackets( | 572 void ForwardErrorCorrection::InsertPackets( |
598 ReceivedPacketList* received_packet_list, | 573 ReceivedPacketList* received_packets, |
599 RecoveredPacketList* recovered_packet_list) { | 574 RecoveredPacketList* recovered_packets) { |
600 while (!received_packet_list->empty()) { | 575 while (!received_packets->empty()) { |
601 ReceivedPacket* rx_packet = received_packet_list->front(); | 576 ReceivedPacket* rx_packet = received_packets->front().get(); |
602 | 577 |
603 // Check for discarding oldest FEC packet, to avoid wrong FEC decoding from | 578 // Check for discarding oldest FEC packet, to avoid wrong FEC decoding from |
604 // sequence number wrap-around. Detection of old FEC packet is based on | 579 // sequence number wrap-around. Detection of old FEC packet is based on |
605 // sequence number difference of received packet and oldest packet in FEC | 580 // sequence number difference of received packet and oldest packet in FEC |
606 // packet list. | 581 // packet list. |
607 // TODO(marpan/holmer): We should be able to improve detection/discarding of | 582 // TODO(marpan/holmer): We should be able to improve detection/discarding of |
608 // old FEC packets based on timestamp information or better sequence number | 583 // old FEC packets based on timestamp information or better sequence number |
609 // thresholding (e.g., to distinguish between wrap-around and reordering). | 584 // thresholding (e.g., to distinguish between wrap-around and reordering). |
610 if (!fec_packet_list_.empty()) { | 585 if (!received_fec_packets_.empty()) { |
611 uint16_t seq_num_diff = | 586 uint16_t seq_num_diff = |
612 abs(static_cast<int>(rx_packet->seq_num) - | 587 abs(static_cast<int>(rx_packet->seq_num) - |
613 static_cast<int>(fec_packet_list_.front()->seq_num)); | 588 static_cast<int>(received_fec_packets_.front()->seq_num)); |
614 if (seq_num_diff > 0x3fff) { | 589 if (seq_num_diff > 0x3fff) { |
615 DiscardFecPacket(fec_packet_list_.front()); | 590 received_fec_packets_.pop_front(); |
616 fec_packet_list_.pop_front(); | |
617 } | 591 } |
618 } | 592 } |
619 | 593 |
620 if (rx_packet->is_fec) { | 594 if (rx_packet->is_fec) { |
621 InsertFecPacket(rx_packet, recovered_packet_list); | 595 InsertFecPacket(rx_packet, recovered_packets); |
622 } else { | 596 } else { |
623 // Insert packet at the end of |recoveredPacketList|. | 597 // Insert packet at the end of |recoveredPacketList|. |
624 InsertMediaPacket(rx_packet, recovered_packet_list); | 598 InsertMediaPacket(rx_packet, recovered_packets); |
625 } | 599 } |
626 // Delete the received packet "wrapper", but not the packet data. | 600 // Delete the received packet "wrapper". |
627 delete rx_packet; | 601 received_packets->pop_front(); |
628 received_packet_list->pop_front(); | |
629 } | 602 } |
630 RTC_DCHECK(received_packet_list->empty()); | 603 RTC_DCHECK(received_packets->empty()); |
631 DiscardOldPackets(recovered_packet_list); | 604 DiscardOldRecoveredPackets(recovered_packets); |
632 } | 605 } |
633 | 606 |
634 bool ForwardErrorCorrection::StartPacketRecovery(const FecPacket* fec_packet, | 607 bool ForwardErrorCorrection::StartPacketRecovery( |
635 RecoveredPacket* recovered) { | 608 const ReceivedFecPacket* fec_packet, |
609 RecoveredPacket* recovered) { | |
636 // This is the first packet which we try to recover with. | 610 // This is the first packet which we try to recover with. |
637 const uint16_t ulp_header_size = fec_packet->pkt->data[0] & 0x40 | 611 const uint16_t ulp_header_size = fec_packet->pkt->data[0] & 0x40 |
638 ? kUlpHeaderSizeLBitSet | 612 ? kUlpHeaderSizeLBitSet |
639 : kUlpHeaderSizeLBitClear; // L bit set? | 613 : kUlpHeaderSizeLBitClear; // L bit set? |
640 if (fec_packet->pkt->length < | 614 if (fec_packet->pkt->length < |
641 static_cast<size_t>(kFecHeaderSize + ulp_header_size)) { | 615 static_cast<size_t>(kFecHeaderSize + ulp_header_size)) { |
642 LOG(LS_WARNING) | 616 LOG(LS_WARNING) |
643 << "Truncated FEC packet doesn't contain room for ULP header."; | 617 << "Truncated FEC packet doesn't contain room for ULP header."; |
644 return false; | 618 return false; |
645 } | 619 } |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
708 dst_packet->length_recovery[1] ^= media_payload_length[1]; | 682 dst_packet->length_recovery[1] ^= media_payload_length[1]; |
709 | 683 |
710 // XOR with RTP payload. | 684 // XOR with RTP payload. |
711 // TODO(marpan/ajm): Are we doing more XORs than required here? | 685 // TODO(marpan/ajm): Are we doing more XORs than required here? |
712 for (size_t i = kRtpHeaderSize; i < src_packet->length; ++i) { | 686 for (size_t i = kRtpHeaderSize; i < src_packet->length; ++i) { |
713 dst_packet->pkt->data[i] ^= src_packet->data[i]; | 687 dst_packet->pkt->data[i] ^= src_packet->data[i]; |
714 } | 688 } |
715 } | 689 } |
716 | 690 |
717 bool ForwardErrorCorrection::RecoverPacket( | 691 bool ForwardErrorCorrection::RecoverPacket( |
718 const FecPacket* fec_packet, | 692 const ReceivedFecPacket* fec_packet, |
719 RecoveredPacket* rec_packet_to_insert) { | 693 RecoveredPacket* rec_packet_to_insert) { |
720 if (!StartPacketRecovery(fec_packet, rec_packet_to_insert)) | 694 if (!StartPacketRecovery(fec_packet, rec_packet_to_insert)) |
721 return false; | 695 return false; |
722 for (const auto* protected_packet : fec_packet->protected_pkt_list) { | 696 for (const auto& protected_packet : fec_packet->protected_pkt_list) { |
723 if (protected_packet->pkt == nullptr) { | 697 if (protected_packet->pkt == nullptr) { |
724 // This is the packet we're recovering. | 698 // This is the packet we're recovering. |
725 rec_packet_to_insert->seq_num = protected_packet->seq_num; | 699 rec_packet_to_insert->seq_num = protected_packet->seq_num; |
726 } else { | 700 } else { |
727 XorPackets(protected_packet->pkt, rec_packet_to_insert); | 701 XorPackets(protected_packet->pkt, rec_packet_to_insert); |
728 } | 702 } |
729 } | 703 } |
730 if (!FinishPacketRecovery(rec_packet_to_insert)) | 704 if (!FinishPacketRecovery(rec_packet_to_insert)) |
731 return false; | 705 return false; |
732 return true; | 706 return true; |
733 } | 707 } |
734 | 708 |
735 void ForwardErrorCorrection::AttemptRecover( | 709 void ForwardErrorCorrection::AttemptRecover( |
736 RecoveredPacketList* recovered_packet_list) { | 710 RecoveredPacketList* recovered_packets) { |
737 auto fec_packet_list_it = fec_packet_list_.begin(); | 711 auto fec_packet_it = received_fec_packets_.begin(); |
738 while (fec_packet_list_it != fec_packet_list_.end()) { | 712 while (fec_packet_it != received_fec_packets_.end()) { |
739 // Search for each FEC packet's protected media packets. | 713 // Search for each FEC packet's protected media packets. |
740 int packets_missing = NumCoveredPacketsMissing(*fec_packet_list_it); | 714 int packets_missing = NumCoveredPacketsMissing(fec_packet_it->get()); |
741 | 715 |
742 // We can only recover one packet with an FEC packet. | 716 // We can only recover one packet with an FEC packet. |
743 if (packets_missing == 1) { | 717 if (packets_missing == 1) { |
744 // Recovery possible. | 718 // Recovery possible. |
745 RecoveredPacket* packet_to_insert = new RecoveredPacket(); | 719 std::unique_ptr<RecoveredPacket> packet_to_insert(new RecoveredPacket()); |
746 packet_to_insert->pkt = nullptr; | 720 packet_to_insert->pkt = nullptr; |
747 if (!RecoverPacket(*fec_packet_list_it, packet_to_insert)) { | 721 if (!RecoverPacket(fec_packet_it->get(), packet_to_insert.get())) { |
748 // Can't recover using this packet, drop it. | 722 // Can't recover using this packet, drop it. |
749 DiscardFecPacket(*fec_packet_list_it); | 723 fec_packet_it = received_fec_packets_.erase(fec_packet_it); |
750 fec_packet_list_it = fec_packet_list_.erase(fec_packet_list_it); | |
751 delete packet_to_insert; | |
752 continue; | 724 continue; |
753 } | 725 } |
754 | 726 |
727 auto packet_to_insert_ptr = packet_to_insert.get(); | |
755 // Add recovered packet to the list of recovered packets and update any | 728 // Add recovered packet to the list of recovered packets and update any |
756 // FEC packets covering this packet with a pointer to the data. | 729 // FEC packets covering this packet with a pointer to the data. |
757 // TODO(holmer): Consider replacing this with a binary search for the | 730 // TODO(holmer): Consider replacing this with a binary search for the |
758 // right position, and then just insert the new packet. Would get rid of | 731 // right position, and then just insert the new packet. Would get rid of |
759 // the sort. | 732 // the sort. |
760 recovered_packet_list->push_back(packet_to_insert); | 733 recovered_packets->push_back(std::move(packet_to_insert)); |
761 recovered_packet_list->sort(SortablePacket::LessThan); | 734 recovered_packets->sort(SortablePacket::LessThan()); |
762 UpdateCoveringFecPackets(packet_to_insert); | 735 UpdateCoveringFecPackets(packet_to_insert_ptr); |
763 DiscardOldPackets(recovered_packet_list); | 736 DiscardOldRecoveredPackets(recovered_packets); |
764 DiscardFecPacket(*fec_packet_list_it); | 737 fec_packet_it = received_fec_packets_.erase(fec_packet_it); |
765 fec_packet_list_it = fec_packet_list_.erase(fec_packet_list_it); | |
766 | 738 |
767 // A packet has been recovered. We need to check the FEC list again, as | 739 // A packet has been recovered. We need to check the FEC list again, as |
768 // this may allow additional packets to be recovered. | 740 // this may allow additional packets to be recovered. |
769 // Restart for first FEC packet. | 741 // Restart for first FEC packet. |
770 fec_packet_list_it = fec_packet_list_.begin(); | 742 fec_packet_it = received_fec_packets_.begin(); |
771 } else if (packets_missing == 0) { | 743 } else if (packets_missing == 0) { |
772 // Either all protected packets arrived or have been recovered. We can | 744 // Either all protected packets arrived or have been recovered. We can |
773 // discard this FEC packet. | 745 // discard this FEC packet. |
774 DiscardFecPacket(*fec_packet_list_it); | 746 fec_packet_it = received_fec_packets_.erase(fec_packet_it); |
775 fec_packet_list_it = fec_packet_list_.erase(fec_packet_list_it); | |
776 } else { | 747 } else { |
777 fec_packet_list_it++; | 748 fec_packet_it++; |
778 } | 749 } |
779 } | 750 } |
780 } | 751 } |
781 | 752 |
782 int ForwardErrorCorrection::NumCoveredPacketsMissing( | 753 int ForwardErrorCorrection::NumCoveredPacketsMissing( |
783 const FecPacket* fec_packet) { | 754 const ReceivedFecPacket* fec_packet) { |
784 int packets_missing = 0; | 755 int packets_missing = 0; |
785 for (const auto* protected_packet : fec_packet->protected_pkt_list) { | 756 for (const auto& protected_packet : fec_packet->protected_pkt_list) { |
786 if (protected_packet->pkt == nullptr) { | 757 if (protected_packet->pkt == nullptr) { |
787 ++packets_missing; | 758 ++packets_missing; |
788 if (packets_missing > 1) { | 759 if (packets_missing > 1) { |
789 break; // We can't recover more than one packet. | 760 break; // We can't recover more than one packet. |
790 } | 761 } |
791 } | 762 } |
792 } | 763 } |
793 return packets_missing; | 764 return packets_missing; |
794 } | 765 } |
795 | 766 |
796 void ForwardErrorCorrection::DiscardFecPacket(FecPacket* fec_packet) { | 767 void ForwardErrorCorrection::DiscardOldRecoveredPackets( |
797 while (!fec_packet->protected_pkt_list.empty()) { | 768 RecoveredPacketList* recovered_packets) { |
798 delete fec_packet->protected_pkt_list.front(); | 769 while (recovered_packets->size() > kMaxMediaPackets) { |
799 fec_packet->protected_pkt_list.pop_front(); | 770 recovered_packets->pop_front(); |
800 } | 771 } |
801 RTC_DCHECK(fec_packet->protected_pkt_list.empty()); | 772 RTC_DCHECK_LE(recovered_packets->size(), kMaxMediaPackets); |
802 delete fec_packet; | |
803 } | |
804 | |
805 void ForwardErrorCorrection::DiscardOldPackets( | |
806 RecoveredPacketList* recovered_packet_list) { | |
807 while (recovered_packet_list->size() > kMaxMediaPackets) { | |
808 ForwardErrorCorrection::RecoveredPacket* packet = | |
809 recovered_packet_list->front(); | |
810 delete packet; | |
811 recovered_packet_list->pop_front(); | |
812 } | |
813 RTC_DCHECK(recovered_packet_list->size() <= kMaxMediaPackets); | |
814 } | 773 } |
815 | 774 |
816 uint16_t ForwardErrorCorrection::ParseSequenceNumber(uint8_t* packet) { | 775 uint16_t ForwardErrorCorrection::ParseSequenceNumber(uint8_t* packet) { |
817 return (packet[2] << 8) + packet[3]; | 776 return (packet[2] << 8) + packet[3]; |
818 } | 777 } |
819 | 778 |
820 int ForwardErrorCorrection::DecodeFec( | 779 int ForwardErrorCorrection::DecodeFec( |
821 ReceivedPacketList* received_packet_list, | 780 ReceivedPacketList* received_packets, |
822 RecoveredPacketList* recovered_packet_list) { | 781 RecoveredPacketList* recovered_packets) { |
823 // TODO(marpan/ajm): can we check for multiple ULP headers, and return an | 782 // TODO(marpan/ajm): can we check for multiple ULP headers, and return an |
824 // error? | 783 // error? |
825 if (recovered_packet_list->size() == kMaxMediaPackets) { | 784 if (recovered_packets->size() == kMaxMediaPackets) { |
826 const unsigned int seq_num_diff = | 785 const unsigned int seq_num_diff = |
827 abs(static_cast<int>(received_packet_list->front()->seq_num) - | 786 abs(static_cast<int>(received_packets->front()->seq_num) - |
828 static_cast<int>(recovered_packet_list->back()->seq_num)); | 787 static_cast<int>(recovered_packets->back()->seq_num)); |
829 if (seq_num_diff > kMaxMediaPackets) { | 788 if (seq_num_diff > kMaxMediaPackets) { |
830 // A big gap in sequence numbers. The old recovered packets | 789 // A big gap in sequence numbers. The old recovered packets |
831 // are now useless, so it's safe to do a reset. | 790 // are now useless, so it's safe to do a reset. |
832 ResetState(recovered_packet_list); | 791 ResetState(recovered_packets); |
833 } | 792 } |
834 } | 793 } |
835 InsertPackets(received_packet_list, recovered_packet_list); | 794 InsertPackets(received_packets, recovered_packets); |
836 AttemptRecover(recovered_packet_list); | 795 AttemptRecover(recovered_packets); |
837 return 0; | 796 return 0; |
838 } | 797 } |
839 | 798 |
840 size_t ForwardErrorCorrection::PacketOverhead() { | 799 size_t ForwardErrorCorrection::PacketOverhead() { |
841 return kFecHeaderSize + kUlpHeaderSizeLBitSet; | 800 return kFecHeaderSize + kUlpHeaderSizeLBitSet; |
842 } | 801 } |
843 } // namespace webrtc | 802 } // namespace webrtc |
OLD | NEW |