aboutsummaryrefslogtreecommitdiff
path: root/modules/rtp_rtcp/source/forward_error_correction.cc
diff options
context:
space:
mode:
Diffstat (limited to 'modules/rtp_rtcp/source/forward_error_correction.cc')
-rw-r--r--modules/rtp_rtcp/source/forward_error_correction.cc31
1 files changed, 24 insertions, 7 deletions
diff --git a/modules/rtp_rtcp/source/forward_error_correction.cc b/modules/rtp_rtcp/source/forward_error_correction.cc
index 56eabc8a7f..da8025d3db 100644
--- a/modules/rtp_rtcp/source/forward_error_correction.cc
+++ b/modules/rtp_rtcp/source/forward_error_correction.cc
@@ -31,6 +31,8 @@ namespace webrtc {
namespace {
// Transport header size in bytes. Assume UDP/IPv4 as a reasonable minimum.
constexpr size_t kTransportOverhead = 28;
+
+constexpr uint16_t kOldSequenceThreshold = 0x3fff;
} // namespace
ForwardErrorCorrection::Packet::Packet() : data(0), ref_count_(0) {}
@@ -508,9 +510,6 @@ void ForwardErrorCorrection::InsertPacket(
// This is important for keeping |received_fec_packets_| sorted, and may
// also reduce the possibility of incorrect decoding due to sequence number
// wrap-around.
- // TODO(marpan/holmer): We should be able to improve detection/discarding of
- // old FEC packets based on timestamp information or better sequence number
- // thresholding (e.g., to distinguish between wrap-around and reordering).
if (!received_fec_packets_.empty() &&
received_packet.ssrc == received_fec_packets_.front()->ssrc) {
// It only makes sense to detect wrap-around when |received_packet|
@@ -521,7 +520,7 @@ void ForwardErrorCorrection::InsertPacket(
auto it = received_fec_packets_.begin();
while (it != received_fec_packets_.end()) {
uint16_t seq_num_diff = MinDiff(received_packet.seq_num, (*it)->seq_num);
- if (seq_num_diff > 0x3fff) {
+ if (seq_num_diff > kOldSequenceThreshold) {
it = received_fec_packets_.erase(it);
} else {
// No need to keep iterating, since |received_fec_packets_| is sorted.
@@ -698,9 +697,10 @@ void ForwardErrorCorrection::AttemptRecovery(
// this may allow additional packets to be recovered.
// Restart for first FEC packet.
fec_packet_it = received_fec_packets_.begin();
- } else if (packets_missing == 0) {
- // Either all protected packets arrived or have been recovered. We can
- // discard this FEC packet.
+ } else if (packets_missing == 0 ||
+ IsOldFecPacket(**fec_packet_it, recovered_packets)) {
+ // Either all protected packets arrived or have been recovered, or the FEC
+ // packet is old. We can discard this FEC packet.
fec_packet_it = received_fec_packets_.erase(fec_packet_it);
} else {
fec_packet_it++;
@@ -731,6 +731,23 @@ void ForwardErrorCorrection::DiscardOldRecoveredPackets(
RTC_DCHECK_LE(recovered_packets->size(), max_media_packets);
}
+bool ForwardErrorCorrection::IsOldFecPacket(
+ const ReceivedFecPacket& fec_packet,
+ const RecoveredPacketList* recovered_packets) {
+ if (recovered_packets->empty()) {
+ return false;
+ }
+
+ const uint16_t back_recovered_seq_num = recovered_packets->back()->seq_num;
+ const uint16_t last_protected_seq_num =
+ fec_packet.protected_packets.back()->seq_num;
+
+ // FEC packet is old if its last protected sequence number is much
+ // older than the latest protected sequence number received.
+ return (MinDiff(back_recovered_seq_num, last_protected_seq_num) >
+ kOldSequenceThreshold);
+}
+
uint16_t ForwardErrorCorrection::ParseSequenceNumber(const uint8_t* packet) {
return (packet[2] << 8) + packet[3];
}