Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(62)

Side by Side Diff: webrtc/modules/rtp_rtcp/source/forward_error_correction.cc

Issue 3012243002: Change ForwardErrorCorrection class to accept one received packet at a time. (Closed)
Patch Set: Fix compilation errors, including tests. Created 3 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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;
brandtr 2017/09/14 11:49:45 Just to verify: the refcount of |received_packet->
nisse-webrtc 2017/09/14 12:55:51 That's my understanding. And it would be more natu
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;
brandtr 2017/09/14 11:49:45 And here.
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698