| 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 |