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 <assert.h> | |
14 #include <stdlib.h> | 13 #include <stdlib.h> |
15 #include <string.h> | 14 #include <string.h> |
16 | 15 |
17 #include <algorithm> | 16 #include <algorithm> |
18 #include <iterator> | 17 #include <iterator> |
19 | 18 |
| 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 const uint8_t kFecHeaderSize = 10; | 28 const uint8_t kFecHeaderSize = 10; |
29 | 29 |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
119 num_important_packets <= num_media_packets); | 119 num_important_packets <= num_media_packets); |
120 assert(fec_packet_list->empty()); | 120 assert(fec_packet_list->empty()); |
121 | 121 |
122 if (num_media_packets > kMaxMediaPackets) { | 122 if (num_media_packets > kMaxMediaPackets) { |
123 LOG(LS_WARNING) << "Can't protect " << num_media_packets | 123 LOG(LS_WARNING) << "Can't protect " << num_media_packets |
124 << " media packets per frame. Max is " << kMaxMediaPackets; | 124 << " media packets per frame. Max is " << kMaxMediaPackets; |
125 return -1; | 125 return -1; |
126 } | 126 } |
127 | 127 |
128 bool l_bit = (num_media_packets > 8 * kMaskSizeLBitClear); | 128 bool l_bit = (num_media_packets > 8 * kMaskSizeLBitClear); |
129 int num_maskBytes = l_bit ? kMaskSizeLBitSet : kMaskSizeLBitClear; | 129 int num_mask_bytes = l_bit ? kMaskSizeLBitSet : kMaskSizeLBitClear; |
130 | 130 |
131 // Do some error checking on the media packets. | 131 // Do some error checking on the media packets. |
132 for (Packet* media_packet : media_packet_list) { | 132 for (Packet* media_packet : media_packet_list) { |
133 assert(media_packet); | 133 assert(media_packet); |
134 | 134 |
135 if (media_packet->length < kRtpHeaderSize) { | 135 if (media_packet->length < kRtpHeaderSize) { |
136 LOG(LS_WARNING) << "Media packet " << media_packet->length << " bytes " | 136 LOG(LS_WARNING) << "Media packet " << media_packet->length << " bytes " |
137 << "is smaller than RTP header."; | 137 << "is smaller than RTP header."; |
138 return -1; | 138 return -1; |
139 } | 139 } |
(...skipping 19 matching lines...) Expand all Loading... |
159 // packets. | 159 // packets. |
160 fec_packet_list->push_back(&generated_fec_packets_[i]); | 160 fec_packet_list->push_back(&generated_fec_packets_[i]); |
161 } | 161 } |
162 | 162 |
163 const internal::PacketMaskTable mask_table(fec_mask_type, num_media_packets); | 163 const internal::PacketMaskTable mask_table(fec_mask_type, num_media_packets); |
164 | 164 |
165 // -- Generate packet masks -- | 165 // -- Generate packet masks -- |
166 // Always allocate space for a large mask. | 166 // Always allocate space for a large mask. |
167 rtc::scoped_ptr<uint8_t[]> packet_mask( | 167 rtc::scoped_ptr<uint8_t[]> packet_mask( |
168 new uint8_t[num_fec_packets * kMaskSizeLBitSet]); | 168 new uint8_t[num_fec_packets * kMaskSizeLBitSet]); |
169 memset(packet_mask.get(), 0, num_fec_packets * num_maskBytes); | 169 memset(packet_mask.get(), 0, num_fec_packets * num_mask_bytes); |
170 internal::GeneratePacketMasks(num_media_packets, num_fec_packets, | 170 internal::GeneratePacketMasks(num_media_packets, num_fec_packets, |
171 num_important_packets, use_unequal_protection, | 171 num_important_packets, use_unequal_protection, |
172 mask_table, packet_mask.get()); | 172 mask_table, packet_mask.get()); |
173 | 173 |
174 int num_mask_bits = InsertZerosInBitMasks( | 174 int num_mask_bits = InsertZerosInBitMasks( |
175 media_packet_list, packet_mask.get(), num_maskBytes, num_fec_packets); | 175 media_packet_list, packet_mask.get(), num_mask_bytes, num_fec_packets); |
176 | |
177 l_bit = (num_mask_bits > 8 * kMaskSizeLBitClear); | |
178 | 176 |
179 if (num_mask_bits < 0) { | 177 if (num_mask_bits < 0) { |
180 return -1; | 178 return -1; |
181 } | 179 } |
| 180 l_bit = (num_mask_bits > 8 * kMaskSizeLBitClear); |
182 if (l_bit) { | 181 if (l_bit) { |
183 num_maskBytes = kMaskSizeLBitSet; | 182 num_mask_bytes = kMaskSizeLBitSet; |
184 } | 183 } |
185 | 184 |
186 GenerateFecBitStrings(media_packet_list, packet_mask.get(), num_fec_packets, | 185 GenerateFecBitStrings(media_packet_list, packet_mask.get(), num_fec_packets, |
187 l_bit); | 186 l_bit); |
188 GenerateFecUlpHeaders(media_packet_list, packet_mask.get(), l_bit, | 187 GenerateFecUlpHeaders(media_packet_list, packet_mask.get(), l_bit, |
189 num_fec_packets); | 188 num_fec_packets); |
190 | 189 |
191 return 0; | 190 return 0; |
192 } | 191 } |
193 | 192 |
194 int ForwardErrorCorrection::GetNumberOfFecPackets(int num_media_packets, | 193 int ForwardErrorCorrection::GetNumberOfFecPackets(int num_media_packets, |
195 int protection_factor) { | 194 int protection_factor) { |
196 // Result in Q0 with an unsigned round. | 195 // Result in Q0 with an unsigned round. |
197 int num_fec_packets = (num_media_packets * protection_factor + (1 << 7)) >> 8; | 196 int num_fec_packets = (num_media_packets * protection_factor + (1 << 7)) >> 8; |
198 // Generate at least one FEC packet if we need protection. | 197 // Generate at least one FEC packet if we need protection. |
199 if (protection_factor > 0 && num_fec_packets == 0) { | 198 if (protection_factor > 0 && num_fec_packets == 0) { |
200 num_fec_packets = 1; | 199 num_fec_packets = 1; |
201 } | 200 } |
202 assert(num_fec_packets <= num_media_packets); | 201 assert(num_fec_packets <= num_media_packets); |
203 return num_fec_packets; | 202 return num_fec_packets; |
204 } | 203 } |
205 | 204 |
206 void ForwardErrorCorrection::GenerateFecBitStrings( | 205 void ForwardErrorCorrection::GenerateFecBitStrings( |
207 const PacketList& media_packet_list, uint8_t* packet_mask, | 206 const PacketList& media_packet_list, uint8_t* packet_mask, |
208 int num_fec_packets, bool l_bit) { | 207 int num_fec_packets, bool l_bit) { |
209 if (media_packet_list.empty()) { | 208 if (media_packet_list.empty()) { |
210 return; | 209 return; |
211 } | 210 } |
212 uint8_t media_payload_length[2]; | 211 uint8_t media_payload_length[2]; |
213 const int num_maskBytes = l_bit ? kMaskSizeLBitSet : kMaskSizeLBitClear; | 212 const int num_mask_bytes = l_bit ? kMaskSizeLBitSet : kMaskSizeLBitClear; |
214 const uint16_t ulp_header_size = | 213 const uint16_t ulp_header_size = |
215 l_bit ? kUlpHeaderSizeLBitSet : kUlpHeaderSizeLBitClear; | 214 l_bit ? kUlpHeaderSizeLBitSet : kUlpHeaderSizeLBitClear; |
216 const uint16_t fec_rtp_offset = | 215 const uint16_t fec_rtp_offset = |
217 kFecHeaderSize + ulp_header_size - kRtpHeaderSize; | 216 kFecHeaderSize + ulp_header_size - kRtpHeaderSize; |
218 | 217 |
219 for (int i = 0; i < num_fec_packets; ++i) { | 218 for (int i = 0; i < num_fec_packets; ++i) { |
220 PacketList::const_iterator media_list_it = media_packet_list.begin(); | 219 PacketList::const_iterator media_list_it = media_packet_list.begin(); |
221 uint32_t pkt_mask_idx = i * num_maskBytes; | 220 uint32_t pkt_mask_idx = i * num_mask_bytes; |
222 uint32_t media_pkt_idx = 0; | 221 uint32_t media_pkt_idx = 0; |
223 uint16_t fec_packet_length = 0; | 222 uint16_t fec_packet_length = 0; |
224 uint16_t prev_seq_num = ParseSequenceNumber((*media_list_it)->data); | 223 uint16_t prev_seq_num = ParseSequenceNumber((*media_list_it)->data); |
225 while (media_list_it != media_packet_list.end()) { | 224 while (media_list_it != media_packet_list.end()) { |
226 // Each FEC packet has a multiple byte mask. | 225 // Each FEC packet has a multiple byte mask. Determine if this media |
| 226 // packet should be included in FEC packet i. |
227 if (packet_mask[pkt_mask_idx] & (1 << (7 - media_pkt_idx))) { | 227 if (packet_mask[pkt_mask_idx] & (1 << (7 - media_pkt_idx))) { |
228 Packet* media_packet = *media_list_it; | 228 Packet* media_packet = *media_list_it; |
229 | 229 |
230 // Assign network-ordered media payload length. | 230 // Assign network-ordered media payload length. |
231 ByteWriter<uint16_t>::WriteBigEndian( | 231 ByteWriter<uint16_t>::WriteBigEndian( |
232 media_payload_length, media_packet->length - kRtpHeaderSize); | 232 media_payload_length, media_packet->length - kRtpHeaderSize); |
233 | 233 |
234 fec_packet_length = media_packet->length + fec_rtp_offset; | 234 fec_packet_length = media_packet->length + fec_rtp_offset; |
235 // On the first protected packet, we don't need to XOR. | 235 // On the first protected packet, we don't need to XOR. |
236 if (generated_fec_packets_[i].length == 0) { | 236 if (generated_fec_packets_[i].length == 0) { |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
270 if (fec_packet_length > generated_fec_packets_[i].length) { | 270 if (fec_packet_length > generated_fec_packets_[i].length) { |
271 generated_fec_packets_[i].length = fec_packet_length; | 271 generated_fec_packets_[i].length = fec_packet_length; |
272 } | 272 } |
273 } | 273 } |
274 media_list_it++; | 274 media_list_it++; |
275 if (media_list_it != media_packet_list.end()) { | 275 if (media_list_it != media_packet_list.end()) { |
276 uint16_t seq_num = ParseSequenceNumber((*media_list_it)->data); | 276 uint16_t seq_num = ParseSequenceNumber((*media_list_it)->data); |
277 media_pkt_idx += static_cast<uint16_t>(seq_num - prev_seq_num); | 277 media_pkt_idx += static_cast<uint16_t>(seq_num - prev_seq_num); |
278 prev_seq_num = seq_num; | 278 prev_seq_num = seq_num; |
279 } | 279 } |
280 if (media_pkt_idx == 8) { | 280 pkt_mask_idx += media_pkt_idx / 8; |
281 // Switch to the next mask byte. | 281 media_pkt_idx %= 8; |
282 media_pkt_idx = 0; | |
283 pkt_mask_idx++; | |
284 } | |
285 } | 282 } |
286 assert(generated_fec_packets_[i].length); | 283 RTC_DCHECK_GT(generated_fec_packets_[i].length, 0u) |
287 //Note: This shouldn't happen: means packet mask is wrong or poorly designed | 284 << "Packet mask is wrong or poorly designed."; |
288 } | 285 } |
289 } | 286 } |
290 | 287 |
291 int ForwardErrorCorrection::InsertZerosInBitMasks( | 288 int ForwardErrorCorrection::InsertZerosInBitMasks( |
292 const PacketList& media_packets, uint8_t* packet_mask, int num_mask_bytes, | 289 const PacketList& media_packets, uint8_t* packet_mask, int num_mask_bytes, |
293 int num_fec_packets) { | 290 int num_fec_packets) { |
294 uint8_t* new_mask = NULL; | 291 uint8_t* new_mask = NULL; |
295 if (media_packets.size() <= 1) { | 292 if (media_packets.size() <= 1) { |
296 return media_packets.size(); | 293 return media_packets.size(); |
297 } | 294 } |
298 int last_seq_num = ParseSequenceNumber(media_packets.back()->data); | 295 int last_seq_num = ParseSequenceNumber(media_packets.back()->data); |
299 int first_seq_num = ParseSequenceNumber(media_packets.front()->data); | 296 int first_seq_num = ParseSequenceNumber(media_packets.front()->data); |
300 int total_missing_seq_nums = | 297 int total_missing_seq_nums = |
301 static_cast<uint16_t>(last_seq_num - first_seq_num) - | 298 static_cast<uint16_t>(last_seq_num - first_seq_num) - |
302 media_packets.size() + 1; | 299 media_packets.size() + 1; |
303 if (total_missing_seq_nums == 0) { | 300 if (total_missing_seq_nums == 0) { |
304 // All sequence numbers are covered by the packet mask. No zero insertion | 301 // All sequence numbers are covered by the packet mask. No zero insertion |
305 // required. | 302 // required. |
306 return media_packets.size(); | 303 return media_packets.size(); |
307 } | 304 } |
| 305 // We can only protect 8 * kMaskSizeLBitSet packets. |
| 306 if (total_missing_seq_nums + media_packets.size() > 8 * kMaskSizeLBitSet) |
| 307 return -1; |
308 // Allocate the new mask. | 308 // Allocate the new mask. |
309 int new_mask_bytes = kMaskSizeLBitClear; | 309 int new_mask_bytes = kMaskSizeLBitClear; |
310 if (media_packets.size() + total_missing_seq_nums > 8 * kMaskSizeLBitClear) { | 310 if (media_packets.size() + total_missing_seq_nums > 8 * kMaskSizeLBitClear) { |
311 new_mask_bytes = kMaskSizeLBitSet; | 311 new_mask_bytes = kMaskSizeLBitSet; |
312 } | 312 } |
313 new_mask = new uint8_t[num_fec_packets * kMaskSizeLBitSet]; | 313 new_mask = new uint8_t[num_fec_packets * kMaskSizeLBitSet]; |
314 memset(new_mask, 0, num_fec_packets * kMaskSizeLBitSet); | 314 memset(new_mask, 0, num_fec_packets * kMaskSizeLBitSet); |
315 | 315 |
316 PacketList::const_iterator it = media_packets.begin(); | 316 PacketList::const_iterator it = media_packets.begin(); |
317 uint16_t prev_seq_num = first_seq_num; | 317 uint16_t prev_seq_num = first_seq_num; |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
403 // 0 1 2 3 | 403 // 0 1 2 3 |
404 // 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 | 404 // 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 |
405 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 405 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
406 // | Protection Length | mask | | 406 // | Protection Length | mask | |
407 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 407 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
408 // | mask cont. (present only when L = 1) | | 408 // | mask cont. (present only when L = 1) | |
409 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 409 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
410 PacketList::const_iterator media_list_it = media_packet_list.begin(); | 410 PacketList::const_iterator media_list_it = media_packet_list.begin(); |
411 Packet* media_packet = *media_list_it; | 411 Packet* media_packet = *media_list_it; |
412 assert(media_packet != NULL); | 412 assert(media_packet != NULL); |
413 int num_maskBytes = l_bit ? kMaskSizeLBitSet : kMaskSizeLBitClear; | 413 int num_mask_bytes = l_bit ? kMaskSizeLBitSet : kMaskSizeLBitClear; |
414 const uint16_t ulp_header_size = | 414 const uint16_t ulp_header_size = |
415 l_bit ? kUlpHeaderSizeLBitSet : kUlpHeaderSizeLBitClear; | 415 l_bit ? kUlpHeaderSizeLBitSet : kUlpHeaderSizeLBitClear; |
416 | 416 |
417 for (int i = 0; i < num_fec_packets; ++i) { | 417 for (int i = 0; i < num_fec_packets; ++i) { |
418 // -- FEC header -- | 418 // -- FEC header -- |
419 generated_fec_packets_[i].data[0] &= 0x7f; // Set E to zero. | 419 generated_fec_packets_[i].data[0] &= 0x7f; // Set E to zero. |
420 if (l_bit == 0) { | 420 if (l_bit == 0) { |
421 generated_fec_packets_[i].data[0] &= 0xbf; // Clear the L bit. | 421 generated_fec_packets_[i].data[0] &= 0xbf; // Clear the L bit. |
422 } else { | 422 } else { |
423 generated_fec_packets_[i].data[0] |= 0x40; // Set the L bit. | 423 generated_fec_packets_[i].data[0] |= 0x40; // Set the L bit. |
424 } | 424 } |
425 // Two byte sequence number from first RTP packet to SN base. | 425 // Two byte sequence number from first RTP packet to SN base. |
426 // We use the same sequence number base for every FEC packet, | 426 // We use the same sequence number base for every FEC packet, |
427 // but that's not required in general. | 427 // but that's not required in general. |
428 memcpy(&generated_fec_packets_[i].data[2], &media_packet->data[2], 2); | 428 memcpy(&generated_fec_packets_[i].data[2], &media_packet->data[2], 2); |
429 | 429 |
430 // -- ULP header -- | 430 // -- ULP header -- |
431 // Copy the payload size to the protection length field. | 431 // Copy the payload size to the protection length field. |
432 // (We protect the entire packet.) | 432 // (We protect the entire packet.) |
433 ByteWriter<uint16_t>::WriteBigEndian( | 433 ByteWriter<uint16_t>::WriteBigEndian( |
434 &generated_fec_packets_[i].data[10], | 434 &generated_fec_packets_[i].data[10], |
435 generated_fec_packets_[i].length - kFecHeaderSize - ulp_header_size); | 435 generated_fec_packets_[i].length - kFecHeaderSize - ulp_header_size); |
436 | 436 |
437 // Copy the packet mask. | 437 // Copy the packet mask. |
438 memcpy(&generated_fec_packets_[i].data[12], &packet_mask[i * num_maskBytes], | 438 memcpy(&generated_fec_packets_[i].data[12], |
439 num_maskBytes); | 439 &packet_mask[i * num_mask_bytes], num_mask_bytes); |
440 } | 440 } |
441 } | 441 } |
442 | 442 |
443 void ForwardErrorCorrection::ResetState( | 443 void ForwardErrorCorrection::ResetState( |
444 RecoveredPacketList* recovered_packet_list) { | 444 RecoveredPacketList* recovered_packet_list) { |
445 fec_packet_received_ = false; | 445 fec_packet_received_ = false; |
446 | 446 |
447 // Free the memory for any existing recovered packets, if the user hasn't. | 447 // Free the memory for any existing recovered packets, if the user hasn't. |
448 while (!recovered_packet_list->empty()) { | 448 while (!recovered_packet_list->empty()) { |
449 delete recovered_packet_list->front(); | 449 delete recovered_packet_list->front(); |
(...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
840 } | 840 } |
841 InsertPackets(received_packet_list, recovered_packet_list); | 841 InsertPackets(received_packet_list, recovered_packet_list); |
842 AttemptRecover(recovered_packet_list); | 842 AttemptRecover(recovered_packet_list); |
843 return 0; | 843 return 0; |
844 } | 844 } |
845 | 845 |
846 size_t ForwardErrorCorrection::PacketOverhead() { | 846 size_t ForwardErrorCorrection::PacketOverhead() { |
847 return kFecHeaderSize + kUlpHeaderSizeLBitSet; | 847 return kFecHeaderSize + kUlpHeaderSizeLBitSet; |
848 } | 848 } |
849 } // namespace webrtc | 849 } // namespace webrtc |
OLD | NEW |