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 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |