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

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

Issue 2918333002: Reland of Only compare sequence numbers from the same SSRC in ForwardErrorCorrection. (Closed)
Patch Set: Let ForwardErrorCorrection be aware of its SSRCs. Created 3 years, 6 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 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
47 } 47 }
48 48
49 // This comparator is used to compare std::unique_ptr's pointing to 49 // This comparator is used to compare std::unique_ptr's pointing to
50 // subclasses of SortablePackets. It needs to be parametric since 50 // subclasses of SortablePackets. It needs to be parametric since
51 // the std::unique_ptr's are not covariant w.r.t. the types that 51 // the std::unique_ptr's are not covariant w.r.t. the types that
52 // they are pointing to. 52 // they are pointing to.
53 template <typename S, typename T> 53 template <typename S, typename T>
54 bool ForwardErrorCorrection::SortablePacket::LessThan::operator() ( 54 bool ForwardErrorCorrection::SortablePacket::LessThan::operator() (
55 const S& first, 55 const S& first,
56 const T& second) { 56 const T& second) {
57 RTC_DCHECK_EQ(first->ssrc, second->ssrc);
57 return IsNewerSequenceNumber(second->seq_num, first->seq_num); 58 return IsNewerSequenceNumber(second->seq_num, first->seq_num);
58 } 59 }
59 60
60 ForwardErrorCorrection::ReceivedPacket::ReceivedPacket() = default; 61 ForwardErrorCorrection::ReceivedPacket::ReceivedPacket() = default;
61 ForwardErrorCorrection::ReceivedPacket::~ReceivedPacket() = default; 62 ForwardErrorCorrection::ReceivedPacket::~ReceivedPacket() = default;
62 63
63 ForwardErrorCorrection::RecoveredPacket::RecoveredPacket() = default; 64 ForwardErrorCorrection::RecoveredPacket::RecoveredPacket() = default;
64 ForwardErrorCorrection::RecoveredPacket::~RecoveredPacket() = default; 65 ForwardErrorCorrection::RecoveredPacket::~RecoveredPacket() = default;
65 66
66 ForwardErrorCorrection::ProtectedPacket::ProtectedPacket() = default; 67 ForwardErrorCorrection::ProtectedPacket::ProtectedPacket() = default;
67 ForwardErrorCorrection::ProtectedPacket::~ProtectedPacket() = default; 68 ForwardErrorCorrection::ProtectedPacket::~ProtectedPacket() = default;
68 69
69 ForwardErrorCorrection::ReceivedFecPacket::ReceivedFecPacket() = default; 70 ForwardErrorCorrection::ReceivedFecPacket::ReceivedFecPacket() = default;
70 ForwardErrorCorrection::ReceivedFecPacket::~ReceivedFecPacket() = default; 71 ForwardErrorCorrection::ReceivedFecPacket::~ReceivedFecPacket() = default;
71 72
72 ForwardErrorCorrection::ForwardErrorCorrection( 73 ForwardErrorCorrection::ForwardErrorCorrection(
73 std::unique_ptr<FecHeaderReader> fec_header_reader, 74 std::unique_ptr<FecHeaderReader> fec_header_reader,
74 std::unique_ptr<FecHeaderWriter> fec_header_writer) 75 std::unique_ptr<FecHeaderWriter> fec_header_writer,
75 : fec_header_reader_(std::move(fec_header_reader)), 76 uint32_t ssrc,
77 uint32_t protected_media_ssrc)
78 : ssrc_(ssrc),
79 protected_media_ssrc_(protected_media_ssrc),
80 fec_header_reader_(std::move(fec_header_reader)),
76 fec_header_writer_(std::move(fec_header_writer)), 81 fec_header_writer_(std::move(fec_header_writer)),
77 generated_fec_packets_(fec_header_writer_->MaxFecPackets()), 82 generated_fec_packets_(fec_header_writer_->MaxFecPackets()),
78 packet_mask_size_(0) {} 83 packet_mask_size_(0) {}
79 84
80 ForwardErrorCorrection::~ForwardErrorCorrection() = default; 85 ForwardErrorCorrection::~ForwardErrorCorrection() = default;
81 86
82 std::unique_ptr<ForwardErrorCorrection> ForwardErrorCorrection::CreateUlpfec() { 87 std::unique_ptr<ForwardErrorCorrection> ForwardErrorCorrection::CreateUlpfec(
88 uint32_t ssrc) {
83 std::unique_ptr<FecHeaderReader> fec_header_reader(new UlpfecHeaderReader()); 89 std::unique_ptr<FecHeaderReader> fec_header_reader(new UlpfecHeaderReader());
84 std::unique_ptr<FecHeaderWriter> fec_header_writer(new UlpfecHeaderWriter()); 90 std::unique_ptr<FecHeaderWriter> fec_header_writer(new UlpfecHeaderWriter());
85 return std::unique_ptr<ForwardErrorCorrection>(new ForwardErrorCorrection( 91 return std::unique_ptr<ForwardErrorCorrection>(new ForwardErrorCorrection(
86 std::move(fec_header_reader), std::move(fec_header_writer))); 92 std::move(fec_header_reader), std::move(fec_header_writer), ssrc, ssrc));
87 } 93 }
88 94
89 std::unique_ptr<ForwardErrorCorrection> 95 std::unique_ptr<ForwardErrorCorrection> ForwardErrorCorrection::CreateFlexfec(
90 ForwardErrorCorrection::CreateFlexfec() { 96 uint32_t ssrc,
97 uint32_t protected_media_ssrc) {
91 std::unique_ptr<FecHeaderReader> fec_header_reader(new FlexfecHeaderReader()); 98 std::unique_ptr<FecHeaderReader> fec_header_reader(new FlexfecHeaderReader());
92 std::unique_ptr<FecHeaderWriter> fec_header_writer(new FlexfecHeaderWriter()); 99 std::unique_ptr<FecHeaderWriter> fec_header_writer(new FlexfecHeaderWriter());
93 return std::unique_ptr<ForwardErrorCorrection>(new ForwardErrorCorrection( 100 return std::unique_ptr<ForwardErrorCorrection>(new ForwardErrorCorrection(
94 std::move(fec_header_reader), std::move(fec_header_writer))); 101 std::move(fec_header_reader), std::move(fec_header_writer), ssrc,
102 protected_media_ssrc));
95 } 103 }
96 104
97 int ForwardErrorCorrection::EncodeFec(const PacketList& media_packets, 105 int ForwardErrorCorrection::EncodeFec(const PacketList& media_packets,
98 uint8_t protection_factor, 106 uint8_t protection_factor,
99 int num_important_packets, 107 int num_important_packets,
100 bool use_unequal_protection, 108 bool use_unequal_protection,
101 FecMaskType fec_mask_type, 109 FecMaskType fec_mask_type,
102 std::list<Packet*>* fec_packets) { 110 std::list<Packet*>* fec_packets) {
103 const size_t num_media_packets = media_packets.size(); 111 const size_t num_media_packets = media_packets.size();
104 112
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after
328 void ForwardErrorCorrection::ResetState( 336 void ForwardErrorCorrection::ResetState(
329 RecoveredPacketList* recovered_packets) { 337 RecoveredPacketList* recovered_packets) {
330 // 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.
331 recovered_packets->clear(); 339 recovered_packets->clear();
332 received_fec_packets_.clear(); 340 received_fec_packets_.clear();
333 } 341 }
334 342
335 void ForwardErrorCorrection::InsertMediaPacket( 343 void ForwardErrorCorrection::InsertMediaPacket(
336 RecoveredPacketList* recovered_packets, 344 RecoveredPacketList* recovered_packets,
337 ReceivedPacket* received_packet) { 345 ReceivedPacket* received_packet) {
346 RTC_DCHECK_EQ(received_packet->ssrc, protected_media_ssrc_);
347
338 // Search for duplicate packets. 348 // Search for duplicate packets.
339 for (const auto& recovered_packet : *recovered_packets) { 349 for (const auto& recovered_packet : *recovered_packets) {
340 if (received_packet->seq_num == recovered_packet->seq_num) { 350 RTC_DCHECK_EQ(recovered_packet->ssrc, received_packet->ssrc);
351 if (recovered_packet->seq_num == received_packet->seq_num) {
341 // Duplicate packet, no need to add to list. 352 // Duplicate packet, no need to add to list.
342 // Delete duplicate media packet data. 353 // Delete duplicate media packet data.
343 received_packet->pkt = nullptr; 354 received_packet->pkt = nullptr;
344 return; 355 return;
345 } 356 }
346 } 357 }
358
347 std::unique_ptr<RecoveredPacket> recovered_packet(new RecoveredPacket()); 359 std::unique_ptr<RecoveredPacket> recovered_packet(new RecoveredPacket());
348 // This "recovered packet" was not recovered using parity packets. 360 // This "recovered packet" was not recovered using parity packets.
349 recovered_packet->was_recovered = false; 361 recovered_packet->was_recovered = false;
350 // This media packet has already been passed on. 362 // This media packet has already been passed on.
351 recovered_packet->returned = true; 363 recovered_packet->returned = true;
364 recovered_packet->ssrc = received_packet->ssrc;
352 recovered_packet->seq_num = received_packet->seq_num; 365 recovered_packet->seq_num = received_packet->seq_num;
353 recovered_packet->pkt = received_packet->pkt; 366 recovered_packet->pkt = received_packet->pkt;
354 recovered_packet->pkt->length = received_packet->pkt->length; 367 recovered_packet->pkt->length = received_packet->pkt->length;
355 // TODO(holmer): Consider replacing this with a binary search for the right 368 // TODO(holmer): Consider replacing this with a binary search for the right
356 // position, and then just insert the new packet. Would get rid of the sort. 369 // position, and then just insert the new packet. Would get rid of the sort.
357 RecoveredPacket* recovered_packet_ptr = recovered_packet.get(); 370 RecoveredPacket* recovered_packet_ptr = recovered_packet.get();
358 recovered_packets->push_back(std::move(recovered_packet)); 371 recovered_packets->push_back(std::move(recovered_packet));
359 recovered_packets->sort(SortablePacket::LessThan()); 372 recovered_packets->sort(SortablePacket::LessThan());
360 UpdateCoveringFecPackets(*recovered_packet_ptr); 373 UpdateCoveringFecPackets(*recovered_packet_ptr);
361 } 374 }
362 375
363 void ForwardErrorCorrection::UpdateCoveringFecPackets( 376 void ForwardErrorCorrection::UpdateCoveringFecPackets(
364 const RecoveredPacket& packet) { 377 const RecoveredPacket& packet) {
365 for (auto& fec_packet : received_fec_packets_) { 378 for (auto& fec_packet : received_fec_packets_) {
366 // Is this FEC packet protecting the media packet |packet|? 379 // Is this FEC packet protecting the media packet |packet|?
367 auto protected_it = std::lower_bound(fec_packet->protected_packets.begin(), 380 auto protected_it = std::lower_bound(fec_packet->protected_packets.begin(),
368 fec_packet->protected_packets.end(), 381 fec_packet->protected_packets.end(),
369 &packet, SortablePacket::LessThan()); 382 &packet, SortablePacket::LessThan());
370 if (protected_it != fec_packet->protected_packets.end() && 383 if (protected_it != fec_packet->protected_packets.end() &&
371 (*protected_it)->seq_num == packet.seq_num) { 384 (*protected_it)->seq_num == packet.seq_num) {
372 // Found an FEC packet which is protecting |packet|. 385 // Found an FEC packet which is protecting |packet|.
373 (*protected_it)->pkt = packet.pkt; 386 (*protected_it)->pkt = packet.pkt;
374 } 387 }
375 } 388 }
376 } 389 }
377 390
378 void ForwardErrorCorrection::InsertFecPacket( 391 void ForwardErrorCorrection::InsertFecPacket(
379 const RecoveredPacketList& recovered_packets, 392 const RecoveredPacketList& recovered_packets,
380 ReceivedPacket* received_packet) { 393 ReceivedPacket* received_packet) {
394 RTC_DCHECK_EQ(received_packet->ssrc, ssrc_);
395
381 // Check for duplicate. 396 // Check for duplicate.
382 for (const auto& existing_fec_packet : received_fec_packets_) { 397 for (const auto& existing_fec_packet : received_fec_packets_) {
383 if (received_packet->seq_num == existing_fec_packet->seq_num) { 398 RTC_DCHECK_EQ(existing_fec_packet->ssrc, received_packet->ssrc);
399 if (existing_fec_packet->seq_num == received_packet->seq_num) {
384 // Delete duplicate FEC packet data. 400 // Delete duplicate FEC packet data.
385 received_packet->pkt = nullptr; 401 received_packet->pkt = nullptr;
386 return; 402 return;
387 } 403 }
388 } 404 }
405
389 std::unique_ptr<ReceivedFecPacket> fec_packet(new ReceivedFecPacket()); 406 std::unique_ptr<ReceivedFecPacket> fec_packet(new ReceivedFecPacket());
390 fec_packet->pkt = received_packet->pkt; 407 fec_packet->pkt = received_packet->pkt;
408 fec_packet->ssrc = received_packet->ssrc;
391 fec_packet->seq_num = received_packet->seq_num; 409 fec_packet->seq_num = received_packet->seq_num;
392 fec_packet->ssrc = received_packet->ssrc;
393 // Parse ULPFEC/FlexFEC header specific info. 410 // Parse ULPFEC/FlexFEC header specific info.
394 bool ret = fec_header_reader_->ReadFecHeader(fec_packet.get()); 411 bool ret = fec_header_reader_->ReadFecHeader(fec_packet.get());
395 if (!ret) { 412 if (!ret) {
396 return; 413 return;
397 } 414 }
415
416 // TODO(brandtr): Update here when we support multistream protection.
417 if (fec_packet->protected_ssrc != protected_media_ssrc_) {
418 LOG(LS_INFO)
419 << "Received FEC packet is protecting an unknown media SSRC; dropping.";
420 return;
421 }
422
398 // Parse packet mask from header and represent as protected packets. 423 // Parse packet mask from header and represent as protected packets.
399 for (uint16_t byte_idx = 0; byte_idx < fec_packet->packet_mask_size; 424 for (uint16_t byte_idx = 0; byte_idx < fec_packet->packet_mask_size;
400 ++byte_idx) { 425 ++byte_idx) {
401 uint8_t packet_mask = 426 uint8_t packet_mask =
402 fec_packet->pkt->data[fec_packet->packet_mask_offset + byte_idx]; 427 fec_packet->pkt->data[fec_packet->packet_mask_offset + byte_idx];
403 for (uint16_t bit_idx = 0; bit_idx < 8; ++bit_idx) { 428 for (uint16_t bit_idx = 0; bit_idx < 8; ++bit_idx) {
404 if (packet_mask & (1 << (7 - bit_idx))) { 429 if (packet_mask & (1 << (7 - bit_idx))) {
405 std::unique_ptr<ProtectedPacket> protected_packet( 430 std::unique_ptr<ProtectedPacket> protected_packet(
406 new ProtectedPacket()); 431 new ProtectedPacket());
407 // This wraps naturally with the sequence number. 432 // This wraps naturally with the sequence number.
433 protected_packet->ssrc = protected_media_ssrc_;
408 protected_packet->seq_num = static_cast<uint16_t>( 434 protected_packet->seq_num = static_cast<uint16_t>(
409 fec_packet->seq_num_base + (byte_idx << 3) + bit_idx); 435 fec_packet->seq_num_base + (byte_idx << 3) + bit_idx);
410 protected_packet->pkt = nullptr; 436 protected_packet->pkt = nullptr;
411 fec_packet->protected_packets.push_back(std::move(protected_packet)); 437 fec_packet->protected_packets.push_back(std::move(protected_packet));
412 } 438 }
413 } 439 }
414 } 440 }
441
415 if (fec_packet->protected_packets.empty()) { 442 if (fec_packet->protected_packets.empty()) {
416 // All-zero packet mask; we can discard this FEC packet. 443 // All-zero packet mask; we can discard this FEC packet.
417 LOG(LS_WARNING) << "Received FEC packet has an all-zero packet mask."; 444 LOG(LS_WARNING) << "Received FEC packet has an all-zero packet mask.";
418 } else { 445 } else {
419 AssignRecoveredPackets(recovered_packets, fec_packet.get()); 446 AssignRecoveredPackets(recovered_packets, fec_packet.get());
420 // TODO(holmer): Consider replacing this with a binary search for the right 447 // TODO(holmer): Consider replacing this with a binary search for the right
421 // position, and then just insert the new packet. Would get rid of the sort. 448 // position, and then just insert the new packet. Would get rid of the sort.
422 //
423 // For correct decoding, |received_fec_packets_| does not necessarily
424 // need to be sorted by sequence number (see decoding algorithm in
425 // AttemptRecover()). By keeping it sorted we try to recover the
426 // oldest lost packets first, however.
427 received_fec_packets_.push_back(std::move(fec_packet)); 449 received_fec_packets_.push_back(std::move(fec_packet));
428 received_fec_packets_.sort(SortablePacket::LessThan()); 450 received_fec_packets_.sort(SortablePacket::LessThan());
429 const size_t max_fec_packets = fec_header_reader_->MaxFecPackets(); 451 const size_t max_fec_packets = fec_header_reader_->MaxFecPackets();
430 if (received_fec_packets_.size() > max_fec_packets) { 452 if (received_fec_packets_.size() > max_fec_packets) {
431 received_fec_packets_.pop_front(); 453 received_fec_packets_.pop_front();
432 } 454 }
433 RTC_DCHECK_LE(received_fec_packets_.size(), max_fec_packets); 455 RTC_DCHECK_LE(received_fec_packets_.size(), max_fec_packets);
434 } 456 }
435 } 457 }
436 458
(...skipping 23 matching lines...) Expand all
460 } 482 }
461 } 483 }
462 } 484 }
463 485
464 void ForwardErrorCorrection::InsertPackets( 486 void ForwardErrorCorrection::InsertPackets(
465 ReceivedPacketList* received_packets, 487 ReceivedPacketList* received_packets,
466 RecoveredPacketList* recovered_packets) { 488 RecoveredPacketList* recovered_packets) {
467 while (!received_packets->empty()) { 489 while (!received_packets->empty()) {
468 ReceivedPacket* received_packet = received_packets->front().get(); 490 ReceivedPacket* received_packet = received_packets->front().get();
469 491
470 // Check for discarding oldest FEC packet, to avoid wrong FEC decoding from 492 // Discard old FEC packets such that the sequence numbers in
471 // sequence number wrap-around. Detection of old FEC packet is based on 493 // |received_fec_packets_| span at most 1/2 of the sequence number space.
472 // sequence number difference of received packet and oldest packet in FEC 494 // This is important for keeping |received_fec_packets_| sorted, and may
473 // packet list. 495 // also reduce the possibility of incorrect decoding due to sequence number
496 // wrap-around.
474 // TODO(marpan/holmer): We should be able to improve detection/discarding of 497 // TODO(marpan/holmer): We should be able to improve detection/discarding of
475 // old FEC packets based on timestamp information or better sequence number 498 // old FEC packets based on timestamp information or better sequence number
476 // thresholding (e.g., to distinguish between wrap-around and reordering). 499 // thresholding (e.g., to distinguish between wrap-around and reordering).
477 if (!received_fec_packets_.empty()) { 500 if (!received_fec_packets_.empty() &&
478 uint16_t seq_num_diff = 501 received_packet->ssrc == received_fec_packets_.front()->ssrc) {
479 abs(static_cast<int>(received_packet->seq_num) - 502 // It only makes sense to detect wrap-around when |received_packet|
480 static_cast<int>(received_fec_packets_.front()->seq_num)); 503 // and |front_received_fec_packet| belong to the same sequence number
481 if (seq_num_diff > 0x3fff) { 504 // space, i.e., the same SSRC. This happens when |received_packet|
482 received_fec_packets_.pop_front(); 505 // is a FEC packet, or if |received_packet| is a media packet and
506 // RED+ULPFEC is used.
507 auto it = received_fec_packets_.begin();
508 while (it != received_fec_packets_.end()) {
509 uint16_t seq_num_diff = abs(static_cast<int>(received_packet->seq_num) -
510 static_cast<int>((*it)->seq_num));
511 if (seq_num_diff > 0x3fff) {
512 it = received_fec_packets_.erase(it);
513 } else {
514 // No need to keep iterating, since |received_fec_packets_| is sorted.
515 break;
516 }
483 } 517 }
484 } 518 }
485 519
486 if (received_packet->is_fec) { 520 if (received_packet->is_fec) {
487 InsertFecPacket(*recovered_packets, received_packet); 521 InsertFecPacket(*recovered_packets, received_packet);
488 } else { 522 } else {
489 InsertMediaPacket(recovered_packets, received_packet); 523 InsertMediaPacket(recovered_packets, received_packet);
490 } 524 }
491 // Delete the received packet "wrapper". 525 // Delete the received packet "wrapper".
492 received_packets->pop_front(); 526 received_packets->pop_front();
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
542 LOG(LS_WARNING) << "The recovered packet had a length larger than a " 576 LOG(LS_WARNING) << "The recovered packet had a length larger than a "
543 << "typical IP packet, and is thus dropped."; 577 << "typical IP packet, and is thus dropped.";
544 return false; 578 return false;
545 } 579 }
546 // Set the SN field. 580 // Set the SN field.
547 ByteWriter<uint16_t>::WriteBigEndian(&recovered_packet->pkt->data[2], 581 ByteWriter<uint16_t>::WriteBigEndian(&recovered_packet->pkt->data[2],
548 recovered_packet->seq_num); 582 recovered_packet->seq_num);
549 // Set the SSRC field. 583 // Set the SSRC field.
550 ByteWriter<uint32_t>::WriteBigEndian(&recovered_packet->pkt->data[8], 584 ByteWriter<uint32_t>::WriteBigEndian(&recovered_packet->pkt->data[8],
551 fec_packet.protected_ssrc); 585 fec_packet.protected_ssrc);
586 recovered_packet->ssrc = fec_packet.protected_ssrc;
552 return true; 587 return true;
553 } 588 }
554 589
555 void ForwardErrorCorrection::XorHeaders(const Packet& src, Packet* dst) { 590 void ForwardErrorCorrection::XorHeaders(const Packet& src, Packet* dst) {
556 // XOR the first 2 bytes of the header: V, P, X, CC, M, PT fields. 591 // XOR the first 2 bytes of the header: V, P, X, CC, M, PT fields.
557 dst->data[0] ^= src.data[0]; 592 dst->data[0] ^= src.data[0];
558 dst->data[1] ^= src.data[1]; 593 dst->data[1] ^= src.data[1];
559 594
560 // XOR the length recovery field. 595 // XOR the length recovery field.
561 uint8_t src_payload_length_network_order[2]; 596 uint8_t src_payload_length_network_order[2];
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
677 return (packet[2] << 8) + packet[3]; 712 return (packet[2] << 8) + packet[3];
678 } 713 }
679 714
680 uint32_t ForwardErrorCorrection::ParseSsrc(uint8_t* packet) { 715 uint32_t ForwardErrorCorrection::ParseSsrc(uint8_t* packet) {
681 return (packet[8] << 24) + (packet[9] << 16) + (packet[10] << 8) + packet[11]; 716 return (packet[8] << 24) + (packet[9] << 16) + (packet[10] << 8) + packet[11];
682 } 717 }
683 718
684 int ForwardErrorCorrection::DecodeFec( 719 int ForwardErrorCorrection::DecodeFec(
685 ReceivedPacketList* received_packets, 720 ReceivedPacketList* received_packets,
686 RecoveredPacketList* recovered_packets) { 721 RecoveredPacketList* recovered_packets) {
687 // TODO(marpan/ajm): can we check for multiple ULP headers, and return an 722 RTC_DCHECK(received_packets);
688 // error? 723 RTC_DCHECK(recovered_packets);
724
689 const size_t max_media_packets = fec_header_reader_->MaxMediaPackets(); 725 const size_t max_media_packets = fec_header_reader_->MaxMediaPackets();
690 if (recovered_packets->size() == max_media_packets) { 726 if (recovered_packets->size() == max_media_packets) {
691 const unsigned int seq_num_diff = 727 const RecoveredPacket* back_recovered_packet =
692 abs(static_cast<int>(received_packets->front()->seq_num) - 728 recovered_packets->back().get();
693 static_cast<int>(recovered_packets->back()->seq_num)); 729 for (const auto& received_packet : *received_packets) {
694 if (seq_num_diff > max_media_packets) { 730 if (received_packet->ssrc == back_recovered_packet->ssrc) {
695 // A big gap in sequence numbers. The old recovered packets 731 const unsigned int seq_num_diff =
696 // are now useless, so it's safe to do a reset. 732 abs(static_cast<int>(received_packet->seq_num) -
697 ResetState(recovered_packets); 733 static_cast<int>(back_recovered_packet->seq_num));
734 if (seq_num_diff > max_media_packets) {
735 // A big gap in sequence numbers. The old recovered packets
736 // are now useless, so it's safe to do a reset.
737 LOG(LS_INFO) << "Big gap in media/ULPFEC sequence numbers. No need "
738 "to keep the old packets in the FEC buffers, thus "
739 "resetting them.";
740 ResetState(recovered_packets);
741 break;
742 }
743 }
698 } 744 }
699 } 745 }
746
700 InsertPackets(received_packets, recovered_packets); 747 InsertPackets(received_packets, recovered_packets);
701 AttemptRecovery(recovered_packets); 748 AttemptRecovery(recovered_packets);
749
702 return 0; 750 return 0;
703 } 751 }
704 752
705 size_t ForwardErrorCorrection::MaxPacketOverhead() const { 753 size_t ForwardErrorCorrection::MaxPacketOverhead() const {
706 return fec_header_writer_->MaxPacketOverhead(); 754 return fec_header_writer_->MaxPacketOverhead();
707 } 755 }
708 756
709 FecHeaderReader::FecHeaderReader(size_t max_media_packets, 757 FecHeaderReader::FecHeaderReader(size_t max_media_packets,
710 size_t max_fec_packets) 758 size_t max_fec_packets)
711 : max_media_packets_(max_media_packets), 759 : max_media_packets_(max_media_packets),
(...skipping 24 matching lines...) Expand all
736 784
737 size_t FecHeaderWriter::MaxFecPackets() const { 785 size_t FecHeaderWriter::MaxFecPackets() const {
738 return max_fec_packets_; 786 return max_fec_packets_;
739 } 787 }
740 788
741 size_t FecHeaderWriter::MaxPacketOverhead() const { 789 size_t FecHeaderWriter::MaxPacketOverhead() const {
742 return max_packet_overhead_; 790 return max_packet_overhead_;
743 } 791 }
744 792
745 } // namespace webrtc 793 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698