Updated comments and renaming of variables in ForwardErrorCorrection.
This CL should have no changes to functionality. BUG=webrtc:5654 Review-Url: https://codereview.webrtc.org/2107703002 Cr-Commit-Position: refs/heads/master@{#13690}
This commit is contained in:
parent
09abaa0c7d
commit
3e2d6ac0c0
@ -138,8 +138,8 @@ int ForwardErrorCorrection::GenerateFec(const PacketList& media_packets,
|
||||
}
|
||||
}
|
||||
|
||||
int num_fec_packets =
|
||||
GetNumberOfFecPackets(num_media_packets, protection_factor);
|
||||
int num_fec_packets = GetNumberOfFecPackets(num_media_packets,
|
||||
protection_factor);
|
||||
if (num_fec_packets == 0) {
|
||||
return 0;
|
||||
}
|
||||
@ -438,51 +438,50 @@ void ForwardErrorCorrection::GenerateFecUlpHeaders(
|
||||
|
||||
void ForwardErrorCorrection::ResetState(
|
||||
RecoveredPacketList* recovered_packets) {
|
||||
// Free the memory for any existing recovered packets, if the user hasn't.
|
||||
// Free the memory for any existing recovered packets, if the caller hasn't.
|
||||
recovered_packets->clear();
|
||||
received_fec_packets_.clear();
|
||||
}
|
||||
|
||||
void ForwardErrorCorrection::InsertMediaPacket(
|
||||
ReceivedPacket* rx_packet,
|
||||
ReceivedPacket* received_packet,
|
||||
RecoveredPacketList* recovered_packets) {
|
||||
|
||||
// Search for duplicate packets.
|
||||
for (const auto& recovered_packet : *recovered_packets) {
|
||||
if (rx_packet->seq_num == recovered_packet->seq_num) {
|
||||
if (received_packet->seq_num == recovered_packet->seq_num) {
|
||||
// Duplicate packet, no need to add to list.
|
||||
// Delete duplicate media packet data.
|
||||
rx_packet->pkt = nullptr;
|
||||
received_packet->pkt = nullptr;
|
||||
return;
|
||||
}
|
||||
}
|
||||
std::unique_ptr<RecoveredPacket> recovered_packet_to_insert(
|
||||
new RecoveredPacket());
|
||||
// This "recovered packet" was not recovered using parity packets.
|
||||
recovered_packet_to_insert->was_recovered = false;
|
||||
// This media packet has already been passed on.
|
||||
recovered_packet_to_insert->returned = true;
|
||||
recovered_packet_to_insert->seq_num = rx_packet->seq_num;
|
||||
recovered_packet_to_insert->pkt = rx_packet->pkt;
|
||||
recovered_packet_to_insert->pkt->length = rx_packet->pkt->length;
|
||||
|
||||
RecoveredPacket* recovered_packet_to_insert_ptr =
|
||||
recovered_packet_to_insert.get();
|
||||
std::unique_ptr<RecoveredPacket> recovered_packet(new RecoveredPacket());
|
||||
// This "recovered packet" was not recovered using parity packets.
|
||||
recovered_packet->was_recovered = false;
|
||||
// This media packet has already been passed on.
|
||||
recovered_packet->returned = true;
|
||||
recovered_packet->seq_num = received_packet->seq_num;
|
||||
recovered_packet->pkt = received_packet->pkt;
|
||||
recovered_packet->pkt->length = received_packet->pkt->length;
|
||||
|
||||
RecoveredPacket* recovered_packet_ptr = recovered_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.
|
||||
recovered_packets->push_back(std::move(recovered_packet_to_insert));
|
||||
recovered_packets->push_back(std::move(recovered_packet));
|
||||
recovered_packets->sort(SortablePacket::LessThan());
|
||||
UpdateCoveringFecPackets(recovered_packet_to_insert_ptr);
|
||||
UpdateCoveringFecPackets(recovered_packet_ptr);
|
||||
}
|
||||
|
||||
void ForwardErrorCorrection::UpdateCoveringFecPackets(RecoveredPacket* packet) {
|
||||
for (auto& fec_packet : received_fec_packets_) {
|
||||
// Is this FEC packet protecting the media packet |packet|?
|
||||
auto protected_it = std::lower_bound(fec_packet->protected_pkt_list.begin(),
|
||||
fec_packet->protected_pkt_list.end(),
|
||||
auto protected_it = std::lower_bound(fec_packet->protected_packets.begin(),
|
||||
fec_packet->protected_packets.end(),
|
||||
packet,
|
||||
SortablePacket::LessThan());
|
||||
if (protected_it != fec_packet->protected_pkt_list.end() &&
|
||||
if (protected_it != fec_packet->protected_packets.end() &&
|
||||
(*protected_it)->seq_num == packet->seq_num) {
|
||||
// Found an FEC packet which is protecting |packet|.
|
||||
(*protected_it)->pkt = packet->pkt;
|
||||
@ -491,28 +490,30 @@ void ForwardErrorCorrection::UpdateCoveringFecPackets(RecoveredPacket* packet) {
|
||||
}
|
||||
|
||||
void ForwardErrorCorrection::InsertFecPacket(
|
||||
ReceivedPacket* rx_packet,
|
||||
ReceivedPacket* received_packet,
|
||||
const RecoveredPacketList* recovered_packets) {
|
||||
// Check for duplicate.
|
||||
for (const auto& existing_fec_packet : received_fec_packets_) {
|
||||
if (rx_packet->seq_num == existing_fec_packet->seq_num) {
|
||||
if (received_packet->seq_num == existing_fec_packet->seq_num) {
|
||||
// Delete duplicate FEC packet data.
|
||||
rx_packet->pkt = nullptr;
|
||||
received_packet->pkt = nullptr;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<ReceivedFecPacket> fec_packet(new ReceivedFecPacket());
|
||||
fec_packet->pkt = rx_packet->pkt;
|
||||
fec_packet->seq_num = rx_packet->seq_num;
|
||||
fec_packet->ssrc = rx_packet->ssrc;
|
||||
fec_packet->pkt = received_packet->pkt;
|
||||
fec_packet->seq_num = received_packet->seq_num;
|
||||
fec_packet->ssrc = received_packet->ssrc;
|
||||
|
||||
const uint16_t seq_num_base =
|
||||
ByteReader<uint16_t>::ReadBigEndian(&fec_packet->pkt->data[2]);
|
||||
const uint16_t maskSizeBytes = (fec_packet->pkt->data[0] & 0x40)
|
||||
? kMaskSizeLBitSet
|
||||
: kMaskSizeLBitClear; // L bit set?
|
||||
const uint16_t mask_size_bytes = (fec_packet->pkt->data[0] & 0x40)
|
||||
? kMaskSizeLBitSet
|
||||
: kMaskSizeLBitClear; // L bit set?
|
||||
|
||||
for (uint16_t byte_idx = 0; byte_idx < maskSizeBytes; ++byte_idx) {
|
||||
// Parse erasure code mask from ULP header and represent as protected packets.
|
||||
for (uint16_t byte_idx = 0; byte_idx < mask_size_bytes; ++byte_idx) {
|
||||
uint8_t packet_mask = fec_packet->pkt->data[12 + byte_idx];
|
||||
for (uint16_t bit_idx = 0; bit_idx < 8; ++bit_idx) {
|
||||
if (packet_mask & (1 << (7 - bit_idx))) {
|
||||
@ -522,13 +523,13 @@ void ForwardErrorCorrection::InsertFecPacket(
|
||||
protected_packet->seq_num =
|
||||
static_cast<uint16_t>(seq_num_base + (byte_idx << 3) + bit_idx);
|
||||
protected_packet->pkt = nullptr;
|
||||
fec_packet->protected_pkt_list.push_back(std::move(protected_packet));
|
||||
fec_packet->protected_packets.push_back(std::move(protected_packet));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fec_packet->protected_pkt_list.empty()) {
|
||||
if (fec_packet->protected_packets.empty()) {
|
||||
// All-zero packet mask; we can discard this FEC packet.
|
||||
LOG(LS_WARNING) << "FEC packet has an all-zero packet mask.";
|
||||
LOG(LS_WARNING) << "Received FEC packet has an all-zero packet mask.";
|
||||
} else {
|
||||
AssignRecoveredPackets(fec_packet.get(), recovered_packets);
|
||||
// TODO(holmer): Consider replacing this with a binary search for the right
|
||||
@ -545,7 +546,7 @@ void ForwardErrorCorrection::InsertFecPacket(
|
||||
void ForwardErrorCorrection::AssignRecoveredPackets(
|
||||
ReceivedFecPacket* fec_packet,
|
||||
const RecoveredPacketList* recovered_packets) {
|
||||
ProtectedPacketList* protected_packets = &fec_packet->protected_pkt_list;
|
||||
ProtectedPacketList* protected_packets = &fec_packet->protected_packets;
|
||||
std::vector<RecoveredPacket*> recovered_protected_packets;
|
||||
|
||||
// Find intersection between the (sorted) containers |protected_packets|
|
||||
@ -573,7 +574,7 @@ void ForwardErrorCorrection::InsertPackets(
|
||||
ReceivedPacketList* received_packets,
|
||||
RecoveredPacketList* recovered_packets) {
|
||||
while (!received_packets->empty()) {
|
||||
ReceivedPacket* rx_packet = received_packets->front().get();
|
||||
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
|
||||
@ -584,18 +585,17 @@ void ForwardErrorCorrection::InsertPackets(
|
||||
// thresholding (e.g., to distinguish between wrap-around and reordering).
|
||||
if (!received_fec_packets_.empty()) {
|
||||
uint16_t seq_num_diff =
|
||||
abs(static_cast<int>(rx_packet->seq_num) -
|
||||
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 (rx_packet->is_fec) {
|
||||
InsertFecPacket(rx_packet, recovered_packets);
|
||||
if (received_packet->is_fec) {
|
||||
InsertFecPacket(received_packet, recovered_packets);
|
||||
} else {
|
||||
// Insert packet at the end of |recoveredPacketList|.
|
||||
InsertMediaPacket(rx_packet, recovered_packets);
|
||||
InsertMediaPacket(received_packet, recovered_packets);
|
||||
}
|
||||
// Delete the received packet "wrapper".
|
||||
received_packets->pop_front();
|
||||
@ -606,7 +606,7 @@ void ForwardErrorCorrection::InsertPackets(
|
||||
|
||||
bool ForwardErrorCorrection::StartPacketRecovery(
|
||||
const ReceivedFecPacket* fec_packet,
|
||||
RecoveredPacket* recovered) {
|
||||
RecoveredPacket* recovered_packet) {
|
||||
// This is the first packet which we try to recover with.
|
||||
const uint16_t ulp_header_size = fec_packet->pkt->data[0] & 0x40
|
||||
? kUlpHeaderSizeLBitSet
|
||||
@ -617,74 +617,77 @@ bool ForwardErrorCorrection::StartPacketRecovery(
|
||||
<< "Truncated FEC packet doesn't contain room for ULP header.";
|
||||
return false;
|
||||
}
|
||||
recovered->pkt = new Packet();
|
||||
memset(recovered->pkt->data, 0, IP_PACKET_SIZE);
|
||||
recovered->returned = false;
|
||||
recovered->was_recovered = true;
|
||||
recovered_packet->pkt = new Packet();
|
||||
memset(recovered_packet->pkt->data, 0, IP_PACKET_SIZE);
|
||||
recovered_packet->returned = false;
|
||||
recovered_packet->was_recovered = true;
|
||||
uint16_t protection_length =
|
||||
ByteReader<uint16_t>::ReadBigEndian(&fec_packet->pkt->data[10]);
|
||||
if (protection_length >
|
||||
std::min(
|
||||
sizeof(recovered->pkt->data) - kRtpHeaderSize,
|
||||
sizeof(recovered_packet->pkt->data) - kRtpHeaderSize,
|
||||
sizeof(fec_packet->pkt->data) - kFecHeaderSize - ulp_header_size)) {
|
||||
LOG(LS_WARNING) << "Incorrect FEC protection length, dropping.";
|
||||
return false;
|
||||
}
|
||||
// Copy FEC payload, skipping the ULP header.
|
||||
memcpy(&recovered->pkt->data[kRtpHeaderSize],
|
||||
memcpy(&recovered_packet->pkt->data[kRtpHeaderSize],
|
||||
&fec_packet->pkt->data[kFecHeaderSize + ulp_header_size],
|
||||
protection_length);
|
||||
// Copy the length recovery field.
|
||||
memcpy(recovered->length_recovery, &fec_packet->pkt->data[8], 2);
|
||||
memcpy(recovered_packet->length_recovery, &fec_packet->pkt->data[8], 2);
|
||||
// Copy the first 2 bytes of the FEC header.
|
||||
memcpy(recovered->pkt->data, fec_packet->pkt->data, 2);
|
||||
memcpy(recovered_packet->pkt->data, fec_packet->pkt->data, 2);
|
||||
// Copy the 5th to 8th bytes of the FEC header.
|
||||
memcpy(&recovered->pkt->data[4], &fec_packet->pkt->data[4], 4);
|
||||
memcpy(&recovered_packet->pkt->data[4], &fec_packet->pkt->data[4], 4);
|
||||
// Set the SSRC field.
|
||||
ByteWriter<uint32_t>::WriteBigEndian(&recovered->pkt->data[8],
|
||||
ByteWriter<uint32_t>::WriteBigEndian(&recovered_packet->pkt->data[8],
|
||||
fec_packet->ssrc);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ForwardErrorCorrection::FinishPacketRecovery(RecoveredPacket* recovered) {
|
||||
bool ForwardErrorCorrection::FinishPacketRecovery(
|
||||
RecoveredPacket* recovered_packet) {
|
||||
// Set the RTP version to 2.
|
||||
recovered->pkt->data[0] |= 0x80; // Set the 1st bit.
|
||||
recovered->pkt->data[0] &= 0xbf; // Clear the 2nd bit.
|
||||
recovered_packet->pkt->data[0] |= 0x80; // Set the 1st bit.
|
||||
recovered_packet->pkt->data[0] &= 0xbf; // Clear the 2nd bit.
|
||||
|
||||
// Set the SN field.
|
||||
ByteWriter<uint16_t>::WriteBigEndian(&recovered->pkt->data[2],
|
||||
recovered->seq_num);
|
||||
ByteWriter<uint16_t>::WriteBigEndian(&recovered_packet->pkt->data[2],
|
||||
recovered_packet->seq_num);
|
||||
// Recover the packet length.
|
||||
recovered->pkt->length =
|
||||
ByteReader<uint16_t>::ReadBigEndian(recovered->length_recovery) +
|
||||
recovered_packet->pkt->length =
|
||||
ByteReader<uint16_t>::ReadBigEndian(recovered_packet->length_recovery) +
|
||||
kRtpHeaderSize;
|
||||
if (recovered->pkt->length > sizeof(recovered->pkt->data) - kRtpHeaderSize)
|
||||
if (recovered_packet->pkt->length >
|
||||
sizeof(recovered_packet->pkt->data) - kRtpHeaderSize) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ForwardErrorCorrection::XorPackets(const Packet* src_packet,
|
||||
RecoveredPacket* dst_packet) {
|
||||
void ForwardErrorCorrection::XorPackets(const Packet* src,
|
||||
RecoveredPacket* dst) {
|
||||
// XOR with the first 2 bytes of the RTP header.
|
||||
for (uint32_t i = 0; i < 2; ++i) {
|
||||
dst_packet->pkt->data[i] ^= src_packet->data[i];
|
||||
dst->pkt->data[i] ^= src->data[i];
|
||||
}
|
||||
// XOR with the 5th to 8th bytes of the RTP header.
|
||||
for (uint32_t i = 4; i < 8; ++i) {
|
||||
dst_packet->pkt->data[i] ^= src_packet->data[i];
|
||||
dst->pkt->data[i] ^= src->data[i];
|
||||
}
|
||||
// XOR with the network-ordered payload size.
|
||||
uint8_t media_payload_length[2];
|
||||
ByteWriter<uint16_t>::WriteBigEndian(media_payload_length,
|
||||
src_packet->length - kRtpHeaderSize);
|
||||
dst_packet->length_recovery[0] ^= media_payload_length[0];
|
||||
dst_packet->length_recovery[1] ^= media_payload_length[1];
|
||||
src->length - kRtpHeaderSize);
|
||||
dst->length_recovery[0] ^= media_payload_length[0];
|
||||
dst->length_recovery[1] ^= media_payload_length[1];
|
||||
|
||||
// XOR with RTP payload.
|
||||
// TODO(marpan/ajm): Are we doing more XORs than required here?
|
||||
for (size_t i = kRtpHeaderSize; i < src_packet->length; ++i) {
|
||||
dst_packet->pkt->data[i] ^= src_packet->data[i];
|
||||
for (size_t i = kRtpHeaderSize; i < src->length; ++i) {
|
||||
dst->pkt->data[i] ^= src->data[i];
|
||||
}
|
||||
}
|
||||
|
||||
@ -693,7 +696,7 @@ bool ForwardErrorCorrection::RecoverPacket(
|
||||
RecoveredPacket* rec_packet_to_insert) {
|
||||
if (!StartPacketRecovery(fec_packet, rec_packet_to_insert))
|
||||
return false;
|
||||
for (const auto& protected_packet : fec_packet->protected_pkt_list) {
|
||||
for (const auto& protected_packet : fec_packet->protected_packets) {
|
||||
if (protected_packet->pkt == nullptr) {
|
||||
// This is the packet we're recovering.
|
||||
rec_packet_to_insert->seq_num = protected_packet->seq_num;
|
||||
@ -753,7 +756,7 @@ void ForwardErrorCorrection::AttemptRecover(
|
||||
int ForwardErrorCorrection::NumCoveredPacketsMissing(
|
||||
const ReceivedFecPacket* fec_packet) {
|
||||
int packets_missing = 0;
|
||||
for (const auto& protected_packet : fec_packet->protected_pkt_list) {
|
||||
for (const auto& protected_packet : fec_packet->protected_packets) {
|
||||
if (protected_packet->pkt == nullptr) {
|
||||
++packets_missing;
|
||||
if (packets_missing > 1) {
|
||||
|
||||
@ -70,19 +70,9 @@ class ForwardErrorCorrection {
|
||||
uint16_t seq_num;
|
||||
};
|
||||
|
||||
// The received list parameter of #DecodeFec() must reference structs of this
|
||||
// type. The last_media_pkt_in_frame is not required to be used for correct
|
||||
// recovery, but will reduce delay by allowing #DecodeFec() to pre-emptively
|
||||
// determine frame completion. If set, we assume a FEC stream, and the
|
||||
// following assumptions must hold:
|
||||
// The received list parameter of DecodeFec() references structs of this type.
|
||||
//
|
||||
// 1. The media packets in a frame have contiguous sequence numbers, i.e. the
|
||||
// frame's FEC packets have sequence numbers either lower than the first
|
||||
// media packet or higher than the last media packet.
|
||||
// 2. All FEC packets have a sequence number base equal to the first media
|
||||
// packet in the corresponding frame.
|
||||
//
|
||||
// The ssrc member is needed to ensure we can restore the SSRC field of
|
||||
// The ssrc member is needed to ensure that we can restore the SSRC field of
|
||||
// recovered packets. In most situations this could be retrieved from other
|
||||
// media packets, but in the case of an FEC packet protecting a single
|
||||
// missing media packet, we have no other means of obtaining it.
|
||||
@ -99,7 +89,7 @@ class ForwardErrorCorrection {
|
||||
rtc::scoped_refptr<Packet> pkt; // Pointer to the packet storage.
|
||||
};
|
||||
|
||||
// The recovered list parameter of #DecodeFec() will reference structs of
|
||||
// The recovered list parameter of #DecodeFec() references structs of
|
||||
// this type.
|
||||
// TODO(holmer): Refactor into a proper class.
|
||||
class RecoveredPacket : public SortablePacket {
|
||||
@ -124,88 +114,85 @@ class ForwardErrorCorrection {
|
||||
ForwardErrorCorrection();
|
||||
virtual ~ForwardErrorCorrection();
|
||||
|
||||
/**
|
||||
* Generates a list of FEC packets from supplied media packets.
|
||||
*
|
||||
* \param[in] mediaPacketList List of media packets to protect, of type
|
||||
* #Packet. All packets must belong to the
|
||||
* same frame and the list must not be empty.
|
||||
* \param[in] protectionFactor FEC protection overhead in the [0, 255]
|
||||
* domain. To obtain 100% overhead, or an
|
||||
* equal number of FEC packets as media
|
||||
* packets, use 255.
|
||||
* \param[in] numImportantPackets The number of "important" packets in the
|
||||
* frame. These packets may receive greater
|
||||
* protection than the remaining packets. The
|
||||
* important packets must be located at the
|
||||
* start of the media packet list. For codecs
|
||||
* with data partitioning, the important
|
||||
* packets may correspond to first partition
|
||||
* packets.
|
||||
* \param[in] useUnequalProtection Parameter to enable/disable unequal
|
||||
* protection (UEP) across packets. Enabling
|
||||
* UEP will allocate more protection to the
|
||||
* numImportantPackets from the start of the
|
||||
* mediaPacketList.
|
||||
* \param[in] fec_mask_type The type of packet mask used in the FEC.
|
||||
* Random or bursty type may be selected. The
|
||||
* bursty type is only defined up to 12 media
|
||||
* packets. If the number of media packets is
|
||||
* above 12, the packets masks from the
|
||||
* random table will be selected.
|
||||
* \param[out] fecPacketList List of FEC packets, of type #Packet. Must
|
||||
* be empty on entry. The memory available
|
||||
* through the list will be valid until the
|
||||
* next call to GenerateFec().
|
||||
*
|
||||
* \return 0 on success, -1 on failure.
|
||||
*/
|
||||
//
|
||||
// Generates a list of FEC packets from supplied media packets.
|
||||
//
|
||||
// Input: media_packets List of media packets to protect, of type
|
||||
// Packet. All packets must belong to the
|
||||
// same frame and the list must not be empty.
|
||||
// Input: protection_factor FEC protection overhead in the [0, 255]
|
||||
// domain. To obtain 100% overhead, or an
|
||||
// equal number of FEC packets as
|
||||
// media packets, use 255.
|
||||
// Input: num_important_packets The number of "important" packets in the
|
||||
// frame. These packets may receive greater
|
||||
// protection than the remaining packets.
|
||||
// The important packets must be located at the
|
||||
// start of the media packet list. For codecs
|
||||
// with data partitioning, the important
|
||||
// packets may correspond to first partition
|
||||
// packets.
|
||||
// Input: use_unequal_protection Parameter to enable/disable unequal
|
||||
// protection (UEP) across packets. Enabling
|
||||
// UEP will allocate more protection to the
|
||||
// num_important_packets from the start of the
|
||||
// media_packets.
|
||||
// Input: fec_mask_type The type of packet mask used in the FEC.
|
||||
// Random or bursty type may be selected. The
|
||||
// bursty type is only defined up to 12 media
|
||||
// packets. If the number of media packets is
|
||||
// above 12, the packet masks from the random
|
||||
// table will be selected.
|
||||
// Output: fec_packets List of pointers to generated FEC packets,
|
||||
// of type Packet. Must be empty on entry.
|
||||
// The memory available through the list will
|
||||
// be valid until the next call to
|
||||
// GenerateFec().
|
||||
//
|
||||
// Returns 0 on success, -1 on failure.
|
||||
//
|
||||
int GenerateFec(const PacketList& media_packets,
|
||||
uint8_t protection_factor, int num_important_packets,
|
||||
bool use_unequal_protection, FecMaskType fec_mask_type,
|
||||
std::list<Packet*>* fec_packets);
|
||||
|
||||
/**
|
||||
* Decodes a list of media and FEC packets. It will parse the input received
|
||||
* packet list, storing FEC packets internally and inserting media packets to
|
||||
* the output recovered packet list. The recovered list will be sorted by
|
||||
* ascending sequence number and have duplicates removed. The function
|
||||
* should be called as new packets arrive, with the recovered list being
|
||||
* progressively assembled with each call. The received packet list will be
|
||||
* empty at output.
|
||||
*
|
||||
* The user will allocate packets submitted through the received list. The
|
||||
* function will handle allocation of recovered packets and optionally
|
||||
* deleting of all packet memory. The user may delete the recovered list
|
||||
* packets, in which case they must remove deleted packets from the
|
||||
* recovered list.
|
||||
*
|
||||
* \param[in] receivedPacketList List of new received packets, of type
|
||||
* #ReceivedPacket, belonging to a single
|
||||
* frame. At output the list will be empty,
|
||||
* with packets either stored internally,
|
||||
* or accessible through the recovered list.
|
||||
* \param[out] recoveredPacketList List of recovered media packets, of type
|
||||
* #RecoveredPacket, belonging to a single
|
||||
* frame. The memory available through the
|
||||
* list will be valid until the next call to
|
||||
* DecodeFec().
|
||||
*
|
||||
* \return 0 on success, -1 on failure.
|
||||
*/
|
||||
//
|
||||
// Decodes a list of received media and FEC packets. It will parse the
|
||||
// |received_packets|, storing FEC packets internally, and move
|
||||
// media packets to |recovered_packets|. The recovered list will be
|
||||
// sorted by ascending sequence number and have duplicates removed.
|
||||
// The function should be called as new packets arrive, and
|
||||
// |recovered_packets| will be progressively assembled with each call.
|
||||
// When the function returns, |received_packets| will be empty.
|
||||
//
|
||||
// The caller will allocate packets submitted through |received_packets|.
|
||||
// The function will handle allocation of recovered packets.
|
||||
//
|
||||
// Input: received_packets List of new received packets, of type
|
||||
// ReceivedPacket, belonging to a single
|
||||
// frame. At output the list will be empty,
|
||||
// with packets either stored internally,
|
||||
// or accessible through the recovered list.
|
||||
// Output: recovered_packets List of recovered media packets, of type
|
||||
// RecoveredPacket, belonging to a single
|
||||
// frame. The memory available through the
|
||||
// list will be valid until the next call to
|
||||
// DecodeFec().
|
||||
//
|
||||
// Returns 0 on success, -1 on failure.
|
||||
//
|
||||
int DecodeFec(ReceivedPacketList* received_packets,
|
||||
RecoveredPacketList* recovered_packets);
|
||||
|
||||
// Get the number of FEC packets, given the number of media packets and the
|
||||
// protection factor.
|
||||
// Get the number of generated FEC packets, given the number of media packets
|
||||
// and the protection factor.
|
||||
int GetNumberOfFecPackets(int num_media_packets, int protection_factor);
|
||||
|
||||
// Gets the size in bytes of the FEC/ULP headers, which must be accounted for
|
||||
// as packet overhead.
|
||||
// \return Packet overhead in bytes.
|
||||
// as packet overhead. Returns the packet overhead in bytes.
|
||||
static size_t PacketOverhead();
|
||||
|
||||
// Reset internal states from last frame and clears |recovered_packets|.
|
||||
// Reset internal states from last frame and clear |recovered_packets|.
|
||||
// Frees all memory allocated by this class.
|
||||
void ResetState(RecoveredPacketList* recovered_packets);
|
||||
|
||||
@ -225,7 +212,7 @@ class ForwardErrorCorrection {
|
||||
// TODO(holmer): Refactor into a proper class.
|
||||
class ReceivedFecPacket : public ForwardErrorCorrection::SortablePacket {
|
||||
public:
|
||||
ProtectedPacketList protected_pkt_list;
|
||||
ProtectedPacketList protected_packets;
|
||||
uint32_t ssrc; // SSRC of the current frame.
|
||||
rtc::scoped_refptr<ForwardErrorCorrection::Packet> pkt;
|
||||
};
|
||||
@ -271,12 +258,13 @@ class ForwardErrorCorrection {
|
||||
uint8_t* packet_mask, int num_fec_packets,
|
||||
bool l_bit);
|
||||
|
||||
// Insert received packets into FEC or recovered list.
|
||||
// Inserts the |received_packets| into the internal received FEC packet list
|
||||
// or into |recovered_packets|.
|
||||
void InsertPackets(ReceivedPacketList* received_packets,
|
||||
RecoveredPacketList* recovered_packets);
|
||||
|
||||
// Insert media packet into recovered packet list. We delete duplicates.
|
||||
void InsertMediaPacket(ReceivedPacket* rx_packet,
|
||||
// Inserts the |received_packet| into |recovered_packets|. Deletes duplicates.
|
||||
void InsertMediaPacket(ReceivedPacket* received_packet,
|
||||
RecoveredPacketList* recovered_packets);
|
||||
|
||||
// Assigns pointers to the recovered packet from all FEC packets which cover
|
||||
@ -286,43 +274,45 @@ class ForwardErrorCorrection {
|
||||
// packets covered by the FEC packet.
|
||||
void UpdateCoveringFecPackets(RecoveredPacket* packet);
|
||||
|
||||
// Insert packet into FEC list. We delete duplicates.
|
||||
void InsertFecPacket(ReceivedPacket* rx_packet,
|
||||
// Insert |received_packet| into internal FEC list. Deletes duplicates.
|
||||
void InsertFecPacket(ReceivedPacket* received_packet,
|
||||
const RecoveredPacketList* recovered_packets);
|
||||
|
||||
// Assigns pointers to already recovered packets covered by this FEC packet.
|
||||
// Assigns pointers to already recovered packets covered by |fec_packet|.
|
||||
static void AssignRecoveredPackets(
|
||||
ReceivedFecPacket* fec_packet,
|
||||
const RecoveredPacketList* recovered_packets);
|
||||
|
||||
// Insert into recovered list in correct position.
|
||||
// Insert |rec_packet_to_insert| into |recovered_packets| in correct position.
|
||||
void InsertRecoveredPacket(RecoveredPacket* rec_packet_to_insert,
|
||||
RecoveredPacketList* recovered_packets);
|
||||
|
||||
// Attempt to recover missing packets.
|
||||
// Attempt to recover missing packets, using the internally stored
|
||||
// received FEC packets.
|
||||
void AttemptRecover(RecoveredPacketList* recovered_packets);
|
||||
|
||||
// Initializes the packet recovery using the FEC packet.
|
||||
// Initializes packet recovery using the received |fec_packet|.
|
||||
static bool StartPacketRecovery(const ReceivedFecPacket* fec_packet,
|
||||
RecoveredPacket* recovered);
|
||||
RecoveredPacket* recovered_packet);
|
||||
|
||||
// Performs XOR between |src_packet| and |dst_packet| and stores the result
|
||||
// in |dst_packet|.
|
||||
static void XorPackets(const Packet* src_packet, RecoveredPacket* dst_packet);
|
||||
// Performs XOR between |src| and |dst| and stores the result in |dst|.
|
||||
static void XorPackets(const Packet* src, RecoveredPacket* dst);
|
||||
|
||||
// Finish up the recovery of a packet.
|
||||
static bool FinishPacketRecovery(RecoveredPacket* recovered);
|
||||
static bool FinishPacketRecovery(RecoveredPacket* recovered_packet);
|
||||
|
||||
// Recover a missing packet.
|
||||
bool RecoverPacket(const ReceivedFecPacket* fec_packet,
|
||||
RecoveredPacket* rec_packet_to_insert);
|
||||
|
||||
// Get the number of missing media packets which are covered by this
|
||||
// FEC packet. An FEC packet can recover at most one packet, and if zero
|
||||
// packets are missing the FEC packet can be discarded.
|
||||
// This function returns 2 when two or more packets are missing.
|
||||
// Get the number of missing media packets which are covered by |fec_packet|.
|
||||
// An FEC packet can recover at most one packet, and if zero packets are
|
||||
// missing the FEC packet can be discarded. This function returns 2 when two
|
||||
// or more packets are missing.
|
||||
static int NumCoveredPacketsMissing(const ReceivedFecPacket* fec_packet);
|
||||
|
||||
// Discards old packets in |recovered_packets|, which are no longer relevant
|
||||
// for recovering lost packets.
|
||||
static void DiscardOldRecoveredPackets(
|
||||
RecoveredPacketList* recovered_packets);
|
||||
static uint16_t ParseSequenceNumber(uint8_t* packet);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user