OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
(...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
335 | 335 |
336 void ForwardErrorCorrection::ResetState( | 336 void ForwardErrorCorrection::ResetState( |
337 RecoveredPacketList* recovered_packets) { | 337 RecoveredPacketList* recovered_packets) { |
338 // Free the memory for any existing recovered packets, if the caller hasn't. | 338 // Free the memory for any existing recovered packets, if the caller hasn't. |
339 recovered_packets->clear(); | 339 recovered_packets->clear(); |
340 received_fec_packets_.clear(); | 340 received_fec_packets_.clear(); |
341 } | 341 } |
342 | 342 |
343 void ForwardErrorCorrection::InsertMediaPacket( | 343 void ForwardErrorCorrection::InsertMediaPacket( |
344 RecoveredPacketList* recovered_packets, | 344 RecoveredPacketList* recovered_packets, |
345 ReceivedPacket* received_packet) { | 345 const ReceivedPacket& received_packet) { |
346 RTC_DCHECK_EQ(received_packet->ssrc, protected_media_ssrc_); | 346 RTC_DCHECK_EQ(received_packet.ssrc, protected_media_ssrc_); |
347 | 347 |
348 // Search for duplicate packets. | 348 // Search for duplicate packets. |
349 for (const auto& recovered_packet : *recovered_packets) { | 349 for (const auto& recovered_packet : *recovered_packets) { |
350 RTC_DCHECK_EQ(recovered_packet->ssrc, received_packet->ssrc); | 350 RTC_DCHECK_EQ(recovered_packet->ssrc, received_packet.ssrc); |
351 if (recovered_packet->seq_num == received_packet->seq_num) { | 351 if (recovered_packet->seq_num == received_packet.seq_num) { |
352 // Duplicate packet, no need to add to list. | 352 // Duplicate packet, no need to add to list. |
353 // Delete duplicate media packet data. | |
354 received_packet->pkt = nullptr; | |
355 return; | 353 return; |
356 } | 354 } |
357 } | 355 } |
358 | 356 |
359 std::unique_ptr<RecoveredPacket> recovered_packet(new RecoveredPacket()); | 357 std::unique_ptr<RecoveredPacket> recovered_packet(new RecoveredPacket()); |
360 // This "recovered packet" was not recovered using parity packets. | 358 // This "recovered packet" was not recovered using parity packets. |
361 recovered_packet->was_recovered = false; | 359 recovered_packet->was_recovered = false; |
362 // This media packet has already been passed on. | 360 // This media packet has already been passed on. |
363 recovered_packet->returned = true; | 361 recovered_packet->returned = true; |
364 recovered_packet->ssrc = received_packet->ssrc; | 362 recovered_packet->ssrc = received_packet.ssrc; |
365 recovered_packet->seq_num = received_packet->seq_num; | 363 recovered_packet->seq_num = received_packet.seq_num; |
366 recovered_packet->pkt = received_packet->pkt; | 364 recovered_packet->pkt = received_packet.pkt; |
367 recovered_packet->pkt->length = received_packet->pkt->length; | 365 recovered_packet->pkt->length = received_packet.pkt->length; |
368 // TODO(holmer): Consider replacing this with a binary search for the right | 366 // TODO(holmer): Consider replacing this with a binary search for the right |
369 // position, and then just insert the new packet. Would get rid of the sort. | 367 // position, and then just insert the new packet. Would get rid of the sort. |
370 RecoveredPacket* recovered_packet_ptr = recovered_packet.get(); | 368 RecoveredPacket* recovered_packet_ptr = recovered_packet.get(); |
371 recovered_packets->push_back(std::move(recovered_packet)); | 369 recovered_packets->push_back(std::move(recovered_packet)); |
372 recovered_packets->sort(SortablePacket::LessThan()); | 370 recovered_packets->sort(SortablePacket::LessThan()); |
373 UpdateCoveringFecPackets(*recovered_packet_ptr); | 371 UpdateCoveringFecPackets(*recovered_packet_ptr); |
374 } | 372 } |
375 | 373 |
376 void ForwardErrorCorrection::UpdateCoveringFecPackets( | 374 void ForwardErrorCorrection::UpdateCoveringFecPackets( |
377 const RecoveredPacket& packet) { | 375 const RecoveredPacket& packet) { |
378 for (auto& fec_packet : received_fec_packets_) { | 376 for (auto& fec_packet : received_fec_packets_) { |
379 // Is this FEC packet protecting the media packet |packet|? | 377 // Is this FEC packet protecting the media packet |packet|? |
380 auto protected_it = std::lower_bound(fec_packet->protected_packets.begin(), | 378 auto protected_it = std::lower_bound(fec_packet->protected_packets.begin(), |
381 fec_packet->protected_packets.end(), | 379 fec_packet->protected_packets.end(), |
382 &packet, SortablePacket::LessThan()); | 380 &packet, SortablePacket::LessThan()); |
383 if (protected_it != fec_packet->protected_packets.end() && | 381 if (protected_it != fec_packet->protected_packets.end() && |
384 (*protected_it)->seq_num == packet.seq_num) { | 382 (*protected_it)->seq_num == packet.seq_num) { |
385 // Found an FEC packet which is protecting |packet|. | 383 // Found an FEC packet which is protecting |packet|. |
386 (*protected_it)->pkt = packet.pkt; | 384 (*protected_it)->pkt = packet.pkt; |
387 } | 385 } |
388 } | 386 } |
389 } | 387 } |
390 | 388 |
391 void ForwardErrorCorrection::InsertFecPacket( | 389 void ForwardErrorCorrection::InsertFecPacket( |
392 const RecoveredPacketList& recovered_packets, | 390 const RecoveredPacketList& recovered_packets, |
393 ReceivedPacket* received_packet) { | 391 const ReceivedPacket& received_packet) { |
394 RTC_DCHECK_EQ(received_packet->ssrc, ssrc_); | 392 RTC_DCHECK_EQ(received_packet.ssrc, ssrc_); |
395 | 393 |
396 // Check for duplicate. | 394 // Check for duplicate. |
397 for (const auto& existing_fec_packet : received_fec_packets_) { | 395 for (const auto& existing_fec_packet : received_fec_packets_) { |
398 RTC_DCHECK_EQ(existing_fec_packet->ssrc, received_packet->ssrc); | 396 RTC_DCHECK_EQ(existing_fec_packet->ssrc, received_packet.ssrc); |
399 if (existing_fec_packet->seq_num == received_packet->seq_num) { | 397 if (existing_fec_packet->seq_num == received_packet.seq_num) { |
400 // Delete duplicate FEC packet data. | 398 // Drop duplicate FEC packet data. |
401 received_packet->pkt = nullptr; | |
402 return; | 399 return; |
403 } | 400 } |
404 } | 401 } |
405 | 402 |
406 std::unique_ptr<ReceivedFecPacket> fec_packet(new ReceivedFecPacket()); | 403 std::unique_ptr<ReceivedFecPacket> fec_packet(new ReceivedFecPacket()); |
407 fec_packet->pkt = received_packet->pkt; | 404 fec_packet->pkt = received_packet.pkt; |
408 fec_packet->ssrc = received_packet->ssrc; | 405 fec_packet->ssrc = received_packet.ssrc; |
409 fec_packet->seq_num = received_packet->seq_num; | 406 fec_packet->seq_num = received_packet.seq_num; |
410 // Parse ULPFEC/FlexFEC header specific info. | 407 // Parse ULPFEC/FlexFEC header specific info. |
411 bool ret = fec_header_reader_->ReadFecHeader(fec_packet.get()); | 408 bool ret = fec_header_reader_->ReadFecHeader(fec_packet.get()); |
412 if (!ret) { | 409 if (!ret) { |
413 return; | 410 return; |
414 } | 411 } |
415 | 412 |
416 // TODO(brandtr): Update here when we support multistream protection. | 413 // TODO(brandtr): Update here when we support multistream protection. |
417 if (fec_packet->protected_ssrc != protected_media_ssrc_) { | 414 if (fec_packet->protected_ssrc != protected_media_ssrc_) { |
418 LOG(LS_INFO) | 415 LOG(LS_INFO) |
419 << "Received FEC packet is protecting an unknown media SSRC; dropping."; | 416 << "Received FEC packet is protecting an unknown media SSRC; dropping."; |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
476 ++it_r; | 473 ++it_r; |
477 } else { // *it_p == *it_r. | 474 } else { // *it_p == *it_r. |
478 // This protected packet has already been recovered. | 475 // This protected packet has already been recovered. |
479 (*it_p)->pkt = (*it_r)->pkt; | 476 (*it_p)->pkt = (*it_r)->pkt; |
480 ++it_p; | 477 ++it_p; |
481 ++it_r; | 478 ++it_r; |
482 } | 479 } |
483 } | 480 } |
484 } | 481 } |
485 | 482 |
486 void ForwardErrorCorrection::InsertPackets( | 483 void ForwardErrorCorrection::InsertPacket( |
487 ReceivedPacketList* received_packets, | 484 const ReceivedPacket& received_packet, |
488 RecoveredPacketList* recovered_packets) { | 485 RecoveredPacketList* recovered_packets) { |
489 while (!received_packets->empty()) { | 486 // Discard old FEC packets such that the sequence numbers in |
490 ReceivedPacket* received_packet = received_packets->front().get(); | 487 // |received_fec_packets_| span at most 1/2 of the sequence number space. |
491 | 488 // This is important for keeping |received_fec_packets_| sorted, and may |
492 // Discard old FEC packets such that the sequence numbers in | 489 // also reduce the possibility of incorrect decoding due to sequence number |
493 // |received_fec_packets_| span at most 1/2 of the sequence number space. | 490 // wrap-around. |
494 // This is important for keeping |received_fec_packets_| sorted, and may | 491 // TODO(marpan/holmer): We should be able to improve detection/discarding of |
495 // also reduce the possibility of incorrect decoding due to sequence number | 492 // old FEC packets based on timestamp information or better sequence number |
496 // wrap-around. | 493 // thresholding (e.g., to distinguish between wrap-around and reordering). |
497 // TODO(marpan/holmer): We should be able to improve detection/discarding of | 494 if (!received_fec_packets_.empty() && |
498 // old FEC packets based on timestamp information or better sequence number | 495 received_packet.ssrc == received_fec_packets_.front()->ssrc) { |
499 // thresholding (e.g., to distinguish between wrap-around and reordering). | 496 // It only makes sense to detect wrap-around when |received_packet| |
500 if (!received_fec_packets_.empty() && | 497 // and |front_received_fec_packet| belong to the same sequence number |
501 received_packet->ssrc == received_fec_packets_.front()->ssrc) { | 498 // space, i.e., the same SSRC. This happens when |received_packet| |
502 // It only makes sense to detect wrap-around when |received_packet| | 499 // is a FEC packet, or if |received_packet| is a media packet and |
503 // and |front_received_fec_packet| belong to the same sequence number | 500 // RED+ULPFEC is used. |
504 // space, i.e., the same SSRC. This happens when |received_packet| | 501 auto it = received_fec_packets_.begin(); |
505 // is a FEC packet, or if |received_packet| is a media packet and | 502 while (it != received_fec_packets_.end()) { |
506 // RED+ULPFEC is used. | 503 // TODO(nisse): This handling of wraparound appears broken, should be |
507 auto it = received_fec_packets_.begin(); | 504 // static_cast<int16_t>( |
508 while (it != received_fec_packets_.end()) { | 505 // received_packet.seq_num - back_recovered_packet->seq_num) |
509 uint16_t seq_num_diff = abs(static_cast<int>(received_packet->seq_num) - | 506 uint16_t seq_num_diff = abs(static_cast<int>(received_packet.seq_num) - |
510 static_cast<int>((*it)->seq_num)); | 507 static_cast<int>((*it)->seq_num)); |
511 if (seq_num_diff > 0x3fff) { | 508 if (seq_num_diff > 0x3fff) { |
512 it = received_fec_packets_.erase(it); | 509 it = received_fec_packets_.erase(it); |
513 } else { | 510 } else { |
514 // No need to keep iterating, since |received_fec_packets_| is sorted. | 511 // No need to keep iterating, since |received_fec_packets_| is sorted. |
515 break; | 512 break; |
516 } | |
517 } | 513 } |
518 } | 514 } |
| 515 } |
519 | 516 |
520 if (received_packet->is_fec) { | 517 if (received_packet.is_fec) { |
521 InsertFecPacket(*recovered_packets, received_packet); | 518 InsertFecPacket(*recovered_packets, received_packet); |
522 } else { | 519 } else { |
523 InsertMediaPacket(recovered_packets, received_packet); | 520 InsertMediaPacket(recovered_packets, received_packet); |
524 } | |
525 // Delete the received packet "wrapper". | |
526 received_packets->pop_front(); | |
527 } | 521 } |
528 RTC_DCHECK(received_packets->empty()); | 522 |
529 DiscardOldRecoveredPackets(recovered_packets); | 523 DiscardOldRecoveredPackets(recovered_packets); |
530 } | 524 } |
531 | 525 |
532 bool ForwardErrorCorrection::StartPacketRecovery( | 526 bool ForwardErrorCorrection::StartPacketRecovery( |
533 const ReceivedFecPacket& fec_packet, | 527 const ReceivedFecPacket& fec_packet, |
534 RecoveredPacket* recovered_packet) { | 528 RecoveredPacket* recovered_packet) { |
535 // Sanity check packet length. | 529 // Sanity check packet length. |
536 if (fec_packet.pkt->length < fec_packet.fec_header_size) { | 530 if (fec_packet.pkt->length < fec_packet.fec_header_size) { |
537 LOG(LS_WARNING) | 531 LOG(LS_WARNING) |
538 << "The FEC packet is truncated: it does not contain enough room " | 532 << "The FEC packet is truncated: it does not contain enough room " |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
709 } | 703 } |
710 | 704 |
711 uint16_t ForwardErrorCorrection::ParseSequenceNumber(uint8_t* packet) { | 705 uint16_t ForwardErrorCorrection::ParseSequenceNumber(uint8_t* packet) { |
712 return (packet[2] << 8) + packet[3]; | 706 return (packet[2] << 8) + packet[3]; |
713 } | 707 } |
714 | 708 |
715 uint32_t ForwardErrorCorrection::ParseSsrc(uint8_t* packet) { | 709 uint32_t ForwardErrorCorrection::ParseSsrc(uint8_t* packet) { |
716 return (packet[8] << 24) + (packet[9] << 16) + (packet[10] << 8) + packet[11]; | 710 return (packet[8] << 24) + (packet[9] << 16) + (packet[10] << 8) + packet[11]; |
717 } | 711 } |
718 | 712 |
719 int ForwardErrorCorrection::DecodeFec( | 713 void ForwardErrorCorrection::DecodeFec(const ReceivedPacket& received_packet, |
720 ReceivedPacketList* received_packets, | 714 RecoveredPacketList* recovered_packets) { |
721 RecoveredPacketList* recovered_packets) { | |
722 RTC_DCHECK(received_packets); | |
723 RTC_DCHECK(recovered_packets); | 715 RTC_DCHECK(recovered_packets); |
724 | 716 |
725 const size_t max_media_packets = fec_header_reader_->MaxMediaPackets(); | 717 const size_t max_media_packets = fec_header_reader_->MaxMediaPackets(); |
726 if (recovered_packets->size() == max_media_packets) { | 718 if (recovered_packets->size() == max_media_packets) { |
727 const RecoveredPacket* back_recovered_packet = | 719 const RecoveredPacket* back_recovered_packet = |
728 recovered_packets->back().get(); | 720 recovered_packets->back().get(); |
729 for (const auto& received_packet : *received_packets) { | 721 |
730 if (received_packet->ssrc == back_recovered_packet->ssrc) { | 722 if (received_packet.ssrc == back_recovered_packet->ssrc) { |
731 const unsigned int seq_num_diff = | 723 // TODO(nisse): This handling of wraparound appears broken, should be |
732 abs(static_cast<int>(received_packet->seq_num) - | 724 // static_cast<int16_t>( |
733 static_cast<int>(back_recovered_packet->seq_num)); | 725 // received_packet.seq_num - back_recovered_packet->seq_num) |
734 if (seq_num_diff > max_media_packets) { | 726 const unsigned int seq_num_diff = |
735 // A big gap in sequence numbers. The old recovered packets | 727 abs(static_cast<int>(received_packet.seq_num) - |
736 // are now useless, so it's safe to do a reset. | 728 static_cast<int>(back_recovered_packet->seq_num)); |
737 LOG(LS_INFO) << "Big gap in media/ULPFEC sequence numbers. No need " | 729 if (seq_num_diff > max_media_packets) { |
738 "to keep the old packets in the FEC buffers, thus " | 730 // A big gap in sequence numbers. The old recovered packets |
739 "resetting them."; | 731 // are now useless, so it's safe to do a reset. |
740 ResetState(recovered_packets); | 732 LOG(LS_INFO) << "Big gap in media/ULPFEC sequence numbers. No need " |
741 break; | 733 "to keep the old packets in the FEC buffers, thus " |
742 } | 734 "resetting them."; |
| 735 ResetState(recovered_packets); |
743 } | 736 } |
744 } | 737 } |
745 } | 738 } |
746 | 739 |
747 InsertPackets(received_packets, recovered_packets); | 740 InsertPacket(received_packet, recovered_packets); |
748 AttemptRecovery(recovered_packets); | 741 AttemptRecovery(recovered_packets); |
749 | |
750 return 0; | |
751 } | 742 } |
752 | 743 |
753 size_t ForwardErrorCorrection::MaxPacketOverhead() const { | 744 size_t ForwardErrorCorrection::MaxPacketOverhead() const { |
754 return fec_header_writer_->MaxPacketOverhead(); | 745 return fec_header_writer_->MaxPacketOverhead(); |
755 } | 746 } |
756 | 747 |
757 FecHeaderReader::FecHeaderReader(size_t max_media_packets, | 748 FecHeaderReader::FecHeaderReader(size_t max_media_packets, |
758 size_t max_fec_packets) | 749 size_t max_fec_packets) |
759 : max_media_packets_(max_media_packets), | 750 : max_media_packets_(max_media_packets), |
760 max_fec_packets_(max_fec_packets) {} | 751 max_fec_packets_(max_fec_packets) {} |
(...skipping 23 matching lines...) Expand all Loading... |
784 | 775 |
785 size_t FecHeaderWriter::MaxFecPackets() const { | 776 size_t FecHeaderWriter::MaxFecPackets() const { |
786 return max_fec_packets_; | 777 return max_fec_packets_; |
787 } | 778 } |
788 | 779 |
789 size_t FecHeaderWriter::MaxPacketOverhead() const { | 780 size_t FecHeaderWriter::MaxPacketOverhead() const { |
790 return max_packet_overhead_; | 781 return max_packet_overhead_; |
791 } | 782 } |
792 | 783 |
793 } // namespace webrtc | 784 } // namespace webrtc |
OLD | NEW |