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

Unified Diff: webrtc/modules/rtp_rtcp/source/forward_error_correction.cc

Issue 2893293003: Only compare sequence numbers from the same SSRC in ForwardErrorCorrection. (Closed)
Patch Set: Typo fix. Created 3 years, 7 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 side-by-side diff with in-line comments
Download patch
Index: webrtc/modules/rtp_rtcp/source/forward_error_correction.cc
diff --git a/webrtc/modules/rtp_rtcp/source/forward_error_correction.cc b/webrtc/modules/rtp_rtcp/source/forward_error_correction.cc
index 8c35f4000f97a848f3d9de5bc382b9b0d1b3ada0..193629b0b9a270bf70819afc60eb323b70cb901e 100644
--- a/webrtc/modules/rtp_rtcp/source/forward_error_correction.cc
+++ b/webrtc/modules/rtp_rtcp/source/forward_error_correction.cc
@@ -54,6 +54,11 @@ template <typename S, typename T>
bool ForwardErrorCorrection::SortablePacket::LessThan::operator() (
const S& first,
const T& second) {
+ // TODO(brandtr): Try to add a DCHECK here, verifying that
+ // first->ssrc == second->ssrc. Currently, it is hard to do so
+ // because we are unable to reliably set the ssrc member on the
+ // ProtectedPacket's. These always belong to the media SSRC, but
+ // we may not know the media SSRC when they are created.
return IsNewerSequenceNumber(second->seq_num, first->seq_num);
}
@@ -337,6 +342,7 @@ void ForwardErrorCorrection::InsertMediaPacket(
ReceivedPacket* received_packet) {
// Search for duplicate packets.
for (const auto& recovered_packet : *recovered_packets) {
+ RTC_DCHECK_EQ(received_packet->ssrc, recovered_packet->ssrc);
if (received_packet->seq_num == recovered_packet->seq_num) {
// Duplicate packet, no need to add to list.
// Delete duplicate media packet data.
@@ -349,6 +355,7 @@ void ForwardErrorCorrection::InsertMediaPacket(
recovered_packet->was_recovered = false;
// This media packet has already been passed on.
recovered_packet->returned = true;
+ recovered_packet->ssrc = received_packet->ssrc;
recovered_packet->seq_num = received_packet->seq_num;
recovered_packet->pkt = received_packet->pkt;
recovered_packet->pkt->length = received_packet->pkt->length;
@@ -380,6 +387,7 @@ void ForwardErrorCorrection::InsertFecPacket(
ReceivedPacket* received_packet) {
// Check for duplicate.
for (const auto& existing_fec_packet : received_fec_packets_) {
+ RTC_DCHECK_EQ(received_packet->ssrc, existing_fec_packet->ssrc);
if (received_packet->seq_num == existing_fec_packet->seq_num) {
// Delete duplicate FEC packet data.
received_packet->pkt = nullptr;
@@ -388,8 +396,8 @@ void ForwardErrorCorrection::InsertFecPacket(
}
std::unique_ptr<ReceivedFecPacket> fec_packet(new ReceivedFecPacket());
fec_packet->pkt = received_packet->pkt;
- fec_packet->seq_num = received_packet->seq_num;
fec_packet->ssrc = received_packet->ssrc;
+ fec_packet->seq_num = received_packet->seq_num;
// Parse ULPFEC/FlexFEC header specific info.
bool ret = fec_header_reader_->ReadFecHeader(fec_packet.get());
if (!ret) {
@@ -419,11 +427,6 @@ void ForwardErrorCorrection::InsertFecPacket(
AssignRecoveredPackets(recovered_packets, fec_packet.get());
// TODO(holmer): Consider replacing this with a binary search for the right
// position, and then just insert the new packet. Would get rid of the sort.
- //
- // For correct decoding, |received_fec_packets_| does not necessarily
- // need to be sorted by sequence number (see decoding algorithm in
- // AttemptRecover()). By keeping it sorted we try to recover the
- // oldest lost packets first, however.
received_fec_packets_.push_back(std::move(fec_packet));
received_fec_packets_.sort(SortablePacket::LessThan());
const size_t max_fec_packets = fec_header_reader_->MaxFecPackets();
@@ -467,19 +470,31 @@ void ForwardErrorCorrection::InsertPackets(
while (!received_packets->empty()) {
ReceivedPacket* received_packet = received_packets->front().get();
- // Check for discarding oldest FEC packet, to avoid wrong FEC decoding from
- // sequence number wrap-around. Detection of old FEC packet is based on
- // sequence number difference of received packet and oldest packet in FEC
- // packet list.
+ // Discard old FEC packets such that the sequence numbers in
+ // |received_fec_packets_| span at most 1/2 of the sequence number space.
+ // 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()) {
- uint16_t seq_num_diff =
- abs(static_cast<int>(received_packet->seq_num) -
- static_cast<int>(received_fec_packets_.front()->seq_num));
- if (seq_num_diff > 0x3fff) {
- received_fec_packets_.pop_front();
+ if (!received_fec_packets_.empty() &&
+ received_packet->ssrc == received_fec_packets_.front()->ssrc) {
+ // It only makes sense to detect wrap-around when |received_packet|
+ // and |front_received_fec_packet| belong to the same sequence number
+ // space, i.e., the same SSRC. This happens when |received_packet|
+ // is a FEC packet, or if |received_packet| is a media packet and
+ // RED+ULPFEC is used.
+ auto it = received_fec_packets_.begin();
+ while (it != received_fec_packets_.end()) {
+ uint16_t seq_num_diff = abs(static_cast<int>(received_packet->seq_num) -
+ static_cast<int>((*it)->seq_num));
+ if (seq_num_diff > 0x3fff) {
+ it = received_fec_packets_.erase(it);
+ } else {
+ // No need to keep iterating, since |received_fec_packets_| is sorted.
+ break;
+ }
}
}
@@ -549,6 +564,7 @@ bool ForwardErrorCorrection::FinishPacketRecovery(
// Set the SSRC field.
ByteWriter<uint32_t>::WriteBigEndian(&recovered_packet->pkt->data[8],
fec_packet.protected_ssrc);
+ recovered_packet->ssrc = fec_packet.protected_ssrc;
return true;
}
@@ -684,21 +700,34 @@ uint32_t ForwardErrorCorrection::ParseSsrc(uint8_t* packet) {
int ForwardErrorCorrection::DecodeFec(
ReceivedPacketList* received_packets,
RecoveredPacketList* recovered_packets) {
- // TODO(marpan/ajm): can we check for multiple ULP headers, and return an
- // error?
+ RTC_DCHECK(received_packets);
+ RTC_DCHECK(recovered_packets);
+
const size_t max_media_packets = fec_header_reader_->MaxMediaPackets();
if (recovered_packets->size() == max_media_packets) {
- const unsigned int seq_num_diff =
- abs(static_cast<int>(received_packets->front()->seq_num) -
- static_cast<int>(recovered_packets->back()->seq_num));
- if (seq_num_diff > max_media_packets) {
- // A big gap in sequence numbers. The old recovered packets
- // are now useless, so it's safe to do a reset.
- ResetState(recovered_packets);
+ const RecoveredPacket* back_recovered_packet =
+ recovered_packets->back().get();
+ for (const auto& received_packet : *received_packets) {
+ if (received_packet->ssrc == back_recovered_packet->ssrc) {
+ const unsigned int seq_num_diff =
+ abs(static_cast<int>(received_packet->seq_num) -
+ static_cast<int>(back_recovered_packet->seq_num));
+ if (seq_num_diff > max_media_packets) {
+ // A big gap in sequence numbers. The old recovered packets
+ // are now useless, so it's safe to do a reset.
+ LOG(LS_INFO) << "Big gap in media/ULPFEC sequence numbers. No need "
+ "to keep the old packets in the FEC buffers, thus "
+ "resetting them.";
+ ResetState(recovered_packets);
+ break;
+ }
+ }
}
}
+
InsertPackets(received_packets, recovered_packets);
AttemptRecovery(recovered_packets);
+
return 0;
}
« no previous file with comments | « webrtc/modules/rtp_rtcp/source/forward_error_correction.h ('k') | webrtc/modules/rtp_rtcp/source/rtp_fec_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698