diff options
Diffstat (limited to 'webrtc/modules/rtp_rtcp/source/forward_error_correction.cc')
-rw-r--r-- | webrtc/modules/rtp_rtcp/source/forward_error_correction.cc | 178 |
1 files changed, 93 insertions, 85 deletions
diff --git a/webrtc/modules/rtp_rtcp/source/forward_error_correction.cc b/webrtc/modules/rtp_rtcp/source/forward_error_correction.cc index aad418f015..b85d813790 100644 --- a/webrtc/modules/rtp_rtcp/source/forward_error_correction.cc +++ b/webrtc/modules/rtp_rtcp/source/forward_error_correction.cc @@ -10,15 +10,15 @@ #include "webrtc/modules/rtp_rtcp/source/forward_error_correction.h" -#include <assert.h> #include <stdlib.h> #include <string.h> #include <algorithm> #include <iterator> +#include "webrtc/base/checks.h" #include "webrtc/base/logging.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" #include "webrtc/modules/rtp_rtcp/source/byte_io.h" #include "webrtc/modules/rtp_rtcp/source/forward_error_correction_internal.h" @@ -36,11 +36,11 @@ const uint8_t kUlpHeaderSizeLBitClear = (2 + kMaskSizeLBitClear); // Transport header size in bytes. Assume UDP/IPv4 as a reasonable minimum. const uint8_t kTransportOverhead = 28; -enum { - kMaxFecPackets = ForwardErrorCorrection::kMaxMediaPackets -}; +enum { kMaxFecPackets = ForwardErrorCorrection::kMaxMediaPackets }; -int32_t ForwardErrorCorrection::Packet::AddRef() { return ++ref_count_; } +int32_t ForwardErrorCorrection::Packet::AddRef() { + return ++ref_count_; +} int32_t ForwardErrorCorrection::Packet::Release() { int32_t ref_count; @@ -72,7 +72,8 @@ class FecPacket : public ForwardErrorCorrection::SortablePacket { }; bool ForwardErrorCorrection::SortablePacket::LessThan( - const SortablePacket* first, const SortablePacket* second) { + const SortablePacket* first, + const SortablePacket* second) { return IsNewerSequenceNumber(second->seq_num, first->seq_num); } @@ -83,8 +84,7 @@ ForwardErrorCorrection::RecoveredPacket::RecoveredPacket() {} ForwardErrorCorrection::RecoveredPacket::~RecoveredPacket() {} ForwardErrorCorrection::ForwardErrorCorrection() - : generated_fec_packets_(kMaxMediaPackets), - fec_packet_received_(false) {} + : generated_fec_packets_(kMaxMediaPackets), fec_packet_received_(false) {} ForwardErrorCorrection::~ForwardErrorCorrection() {} @@ -112,7 +112,6 @@ int32_t ForwardErrorCorrection::GenerateFEC(const PacketList& media_packet_list, FecMaskType fec_mask_type, PacketList* fec_packet_list) { const uint16_t num_media_packets = media_packet_list.size(); - // Sanity check arguments. assert(num_media_packets > 0); assert(num_important_packets >= 0 && @@ -126,12 +125,10 @@ int32_t ForwardErrorCorrection::GenerateFEC(const PacketList& media_packet_list, } bool l_bit = (num_media_packets > 8 * kMaskSizeLBitClear); - int num_maskBytes = l_bit ? kMaskSizeLBitSet : kMaskSizeLBitClear; + int num_mask_bytes = l_bit ? kMaskSizeLBitSet : kMaskSizeLBitClear; // Do some error checking on the media packets. - PacketList::const_iterator media_list_it = media_packet_list.begin(); - while (media_list_it != media_packet_list.end()) { - Packet* media_packet = *media_list_it; + for (Packet* media_packet : media_packet_list) { assert(media_packet); if (media_packet->length < kRtpHeaderSize) { @@ -146,7 +143,6 @@ int32_t ForwardErrorCorrection::GenerateFEC(const PacketList& media_packet_list, LOG(LS_WARNING) << "Media packet " << media_packet->length << " bytes " << "with overhead is larger than " << IP_PACKET_SIZE; } - media_list_it++; } int num_fec_packets = @@ -167,29 +163,29 @@ int32_t ForwardErrorCorrection::GenerateFEC(const PacketList& media_packet_list, // -- Generate packet masks -- // Always allocate space for a large mask. - uint8_t* packet_mask = new uint8_t[num_fec_packets * kMaskSizeLBitSet]; - memset(packet_mask, 0, num_fec_packets * num_maskBytes); + rtc::scoped_ptr<uint8_t[]> packet_mask( + new uint8_t[num_fec_packets * kMaskSizeLBitSet]); + memset(packet_mask.get(), 0, num_fec_packets * num_mask_bytes); internal::GeneratePacketMasks(num_media_packets, num_fec_packets, num_important_packets, use_unequal_protection, - mask_table, packet_mask); - - int num_maskBits = InsertZerosInBitMasks(media_packet_list, packet_mask, - num_maskBytes, num_fec_packets); + mask_table, packet_mask.get()); - l_bit = (num_maskBits > 8 * kMaskSizeLBitClear); + int num_mask_bits = InsertZerosInBitMasks( + media_packet_list, packet_mask.get(), num_mask_bytes, num_fec_packets); - if (num_maskBits < 0) { - delete[] packet_mask; + if (num_mask_bits < 0) { return -1; } + l_bit = (num_mask_bits > 8 * kMaskSizeLBitClear); if (l_bit) { - num_maskBytes = kMaskSizeLBitSet; + num_mask_bytes = kMaskSizeLBitSet; } - GenerateFecBitStrings(media_packet_list, packet_mask, num_fec_packets, l_bit); - GenerateFecUlpHeaders(media_packet_list, packet_mask, l_bit, num_fec_packets); + GenerateFecBitStrings(media_packet_list, packet_mask.get(), num_fec_packets, + l_bit); + GenerateFecUlpHeaders(media_packet_list, packet_mask.get(), l_bit, + num_fec_packets); - delete[] packet_mask; return 0; } @@ -206,26 +202,30 @@ int ForwardErrorCorrection::GetNumberOfFecPackets(int num_media_packets, } void ForwardErrorCorrection::GenerateFecBitStrings( - const PacketList& media_packet_list, uint8_t* packet_mask, - int num_fec_packets, bool l_bit) { + const PacketList& media_packet_list, + uint8_t* packet_mask, + int num_fec_packets, + bool l_bit) { if (media_packet_list.empty()) { return; } uint8_t media_payload_length[2]; - const int num_maskBytes = l_bit ? kMaskSizeLBitSet : kMaskSizeLBitClear; + const int num_mask_bytes = l_bit ? kMaskSizeLBitSet : kMaskSizeLBitClear; const uint16_t ulp_header_size = l_bit ? kUlpHeaderSizeLBitSet : kUlpHeaderSizeLBitClear; const uint16_t fec_rtp_offset = kFecHeaderSize + ulp_header_size - kRtpHeaderSize; for (int i = 0; i < num_fec_packets; ++i) { + Packet* const fec_packet = &generated_fec_packets_[i]; PacketList::const_iterator media_list_it = media_packet_list.begin(); - uint32_t pkt_mask_idx = i * num_maskBytes; + uint32_t pkt_mask_idx = i * num_mask_bytes; uint32_t media_pkt_idx = 0; uint16_t fec_packet_length = 0; uint16_t prev_seq_num = ParseSequenceNumber((*media_list_it)->data); while (media_list_it != media_packet_list.end()) { - // Each FEC packet has a multiple byte mask. + // Each FEC packet has a multiple byte mask. Determine if this media + // packet should be included in FEC packet i. if (packet_mask[pkt_mask_idx] & (1 << (7 - media_pkt_idx))) { Packet* media_packet = *media_list_it; @@ -235,42 +235,40 @@ void ForwardErrorCorrection::GenerateFecBitStrings( fec_packet_length = media_packet->length + fec_rtp_offset; // On the first protected packet, we don't need to XOR. - if (generated_fec_packets_[i].length == 0) { + if (fec_packet->length == 0) { // Copy the first 2 bytes of the RTP header. - memcpy(generated_fec_packets_[i].data, media_packet->data, 2); + memcpy(fec_packet->data, media_packet->data, 2); // Copy the 5th to 8th bytes of the RTP header. - memcpy(&generated_fec_packets_[i].data[4], &media_packet->data[4], 4); + memcpy(&fec_packet->data[4], &media_packet->data[4], 4); // Copy network-ordered payload size. - memcpy(&generated_fec_packets_[i].data[8], media_payload_length, 2); + memcpy(&fec_packet->data[8], media_payload_length, 2); // Copy RTP payload, leaving room for the ULP header. - memcpy( - &generated_fec_packets_[i].data[kFecHeaderSize + ulp_header_size], - &media_packet->data[kRtpHeaderSize], - media_packet->length - kRtpHeaderSize); + memcpy(&fec_packet->data[kFecHeaderSize + ulp_header_size], + &media_packet->data[kRtpHeaderSize], + media_packet->length - kRtpHeaderSize); } else { // XOR with the first 2 bytes of the RTP header. - generated_fec_packets_[i].data[0] ^= media_packet->data[0]; - generated_fec_packets_[i].data[1] ^= media_packet->data[1]; + fec_packet->data[0] ^= media_packet->data[0]; + fec_packet->data[1] ^= media_packet->data[1]; // XOR with the 5th to 8th bytes of the RTP header. for (uint32_t j = 4; j < 8; ++j) { - generated_fec_packets_[i].data[j] ^= media_packet->data[j]; + fec_packet->data[j] ^= media_packet->data[j]; } // XOR with the network-ordered payload size. - generated_fec_packets_[i].data[8] ^= media_payload_length[0]; - generated_fec_packets_[i].data[9] ^= media_payload_length[1]; + fec_packet->data[8] ^= media_payload_length[0]; + fec_packet->data[9] ^= media_payload_length[1]; // XOR with RTP payload, leaving room for the ULP header. for (int32_t j = kFecHeaderSize + ulp_header_size; j < fec_packet_length; j++) { - generated_fec_packets_[i].data[j] ^= - media_packet->data[j - fec_rtp_offset]; + fec_packet->data[j] ^= media_packet->data[j - fec_rtp_offset]; } } - if (fec_packet_length > generated_fec_packets_[i].length) { - generated_fec_packets_[i].length = fec_packet_length; + if (fec_packet_length > fec_packet->length) { + fec_packet->length = fec_packet_length; } } media_list_it++; @@ -279,19 +277,18 @@ void ForwardErrorCorrection::GenerateFecBitStrings( media_pkt_idx += static_cast<uint16_t>(seq_num - prev_seq_num); prev_seq_num = seq_num; } - if (media_pkt_idx == 8) { - // Switch to the next mask byte. - media_pkt_idx = 0; - pkt_mask_idx++; - } + pkt_mask_idx += media_pkt_idx / 8; + media_pkt_idx %= 8; } - assert(generated_fec_packets_[i].length); - //Note: This shouldn't happen: means packet mask is wrong or poorly designed + RTC_DCHECK_GT(fec_packet->length, 0u) + << "Packet mask is wrong or poorly designed."; } } int ForwardErrorCorrection::InsertZerosInBitMasks( - const PacketList& media_packets, uint8_t* packet_mask, int num_mask_bytes, + const PacketList& media_packets, + uint8_t* packet_mask, + int num_mask_bytes, int num_fec_packets) { uint8_t* new_mask = NULL; if (media_packets.size() <= 1) { @@ -307,6 +304,9 @@ int ForwardErrorCorrection::InsertZerosInBitMasks( // required. return media_packets.size(); } + // We can only protect 8 * kMaskSizeLBitSet packets. + if (total_missing_seq_nums + media_packets.size() > 8 * kMaskSizeLBitSet) + return -1; // Allocate the new mask. int new_mask_bytes = kMaskSizeLBitClear; if (media_packets.size() + total_missing_seq_nums > 8 * kMaskSizeLBitClear) { @@ -357,7 +357,8 @@ int ForwardErrorCorrection::InsertZerosInBitMasks( return new_bit_index; } -void ForwardErrorCorrection::InsertZeroColumns(int num_zeros, uint8_t* new_mask, +void ForwardErrorCorrection::InsertZeroColumns(int num_zeros, + uint8_t* new_mask, int new_mask_bytes, int num_fec_packets, int new_bit_index) { @@ -368,9 +369,12 @@ void ForwardErrorCorrection::InsertZeroColumns(int num_zeros, uint8_t* new_mask, } } -void ForwardErrorCorrection::CopyColumn(uint8_t* new_mask, int new_mask_bytes, - uint8_t* old_mask, int old_mask_bytes, - int num_fec_packets, int new_bit_index, +void ForwardErrorCorrection::CopyColumn(uint8_t* new_mask, + int new_mask_bytes, + uint8_t* old_mask, + int old_mask_bytes, + int num_fec_packets, + int new_bit_index, int old_bit_index) { // Copy column from the old mask to the beginning of the new mask and shift it // out from the old mask. @@ -386,7 +390,9 @@ void ForwardErrorCorrection::CopyColumn(uint8_t* new_mask, int new_mask_bytes, } void ForwardErrorCorrection::GenerateFecUlpHeaders( - const PacketList& media_packet_list, uint8_t* packet_mask, bool l_bit, + const PacketList& media_packet_list, + uint8_t* packet_mask, + bool l_bit, int num_fec_packets) { // -- Generate FEC and ULP headers -- // @@ -412,33 +418,34 @@ void ForwardErrorCorrection::GenerateFecUlpHeaders( PacketList::const_iterator media_list_it = media_packet_list.begin(); Packet* media_packet = *media_list_it; assert(media_packet != NULL); - int num_maskBytes = l_bit ? kMaskSizeLBitSet : kMaskSizeLBitClear; + int num_mask_bytes = l_bit ? kMaskSizeLBitSet : kMaskSizeLBitClear; const uint16_t ulp_header_size = l_bit ? kUlpHeaderSizeLBitSet : kUlpHeaderSizeLBitClear; for (int i = 0; i < num_fec_packets; ++i) { + Packet* const fec_packet = &generated_fec_packets_[i]; // -- FEC header -- - generated_fec_packets_[i].data[0] &= 0x7f; // Set E to zero. + fec_packet->data[0] &= 0x7f; // Set E to zero. if (l_bit == 0) { - generated_fec_packets_[i].data[0] &= 0xbf; // Clear the L bit. + fec_packet->data[0] &= 0xbf; // Clear the L bit. } else { - generated_fec_packets_[i].data[0] |= 0x40; // Set the L bit. + fec_packet->data[0] |= 0x40; // Set the L bit. } // Two byte sequence number from first RTP packet to SN base. // We use the same sequence number base for every FEC packet, // but that's not required in general. - memcpy(&generated_fec_packets_[i].data[2], &media_packet->data[2], 2); + memcpy(&fec_packet->data[2], &media_packet->data[2], 2); // -- ULP header -- // Copy the payload size to the protection length field. // (We protect the entire packet.) ByteWriter<uint16_t>::WriteBigEndian( - &generated_fec_packets_[i].data[10], - generated_fec_packets_[i].length - kFecHeaderSize - ulp_header_size); + &fec_packet->data[10], + fec_packet->length - kFecHeaderSize - ulp_header_size); // Copy the packet mask. - memcpy(&generated_fec_packets_[i].data[12], &packet_mask[i * num_maskBytes], - num_maskBytes); + memcpy(&fec_packet->data[12], &packet_mask[i * num_mask_bytes], + num_mask_bytes); } } @@ -460,7 +467,7 @@ void ForwardErrorCorrection::ResetState( ProtectedPacketList::iterator protected_packet_list_it; protected_packet_list_it = fec_packet->protected_pkt_list.begin(); while (protected_packet_list_it != fec_packet->protected_pkt_list.end()) { - delete* protected_packet_list_it; + delete *protected_packet_list_it; protected_packet_list_it = fec_packet->protected_pkt_list.erase(protected_packet_list_it); } @@ -472,7 +479,8 @@ void ForwardErrorCorrection::ResetState( } void ForwardErrorCorrection::InsertMediaPacket( - ReceivedPacket* rx_packet, RecoveredPacketList* recovered_packet_list) { + ReceivedPacket* rx_packet, + RecoveredPacketList* recovered_packet_list) { RecoveredPacketList::iterator recovered_packet_list_it = recovered_packet_list->begin(); @@ -538,9 +546,9 @@ void ForwardErrorCorrection::InsertFECPacket( 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 maskSizeBytes = (fec_packet->pkt->data[0] & 0x40) + ? kMaskSizeLBitSet + : kMaskSizeLBitClear; // L bit set? for (uint16_t byte_idx = 0; byte_idx < maskSizeBytes; ++byte_idx) { uint8_t packet_mask = fec_packet->pkt->data[12 + byte_idx]; @@ -574,7 +582,8 @@ void ForwardErrorCorrection::InsertFECPacket( } void ForwardErrorCorrection::AssignRecoveredPackets( - FecPacket* fec_packet, const RecoveredPacketList* recovered_packets) { + FecPacket* fec_packet, + const RecoveredPacketList* recovered_packets) { // Search for missing packets which have arrived or have been recovered by // another FEC packet. ProtectedPacketList* not_recovered = &fec_packet->protected_pkt_list; @@ -599,7 +608,6 @@ void ForwardErrorCorrection::AssignRecoveredPackets( void ForwardErrorCorrection::InsertPackets( ReceivedPacketList* received_packet_list, RecoveredPacketList* recovered_packet_list) { - while (!received_packet_list->empty()) { ReceivedPacket* rx_packet = received_packet_list->front(); @@ -611,9 +619,9 @@ void ForwardErrorCorrection::InsertPackets( // old FEC packets based on timestamp information or better sequence number // thresholding (e.g., to distinguish between wrap-around and reordering). if (!fec_packet_list_.empty()) { - uint16_t seq_num_diff = abs( - static_cast<int>(rx_packet->seq_num) - - static_cast<int>(fec_packet_list_.front()->seq_num)); + uint16_t seq_num_diff = + abs(static_cast<int>(rx_packet->seq_num) - + static_cast<int>(fec_packet_list_.front()->seq_num)); if (seq_num_diff > 0x3fff) { DiscardFECPacket(fec_packet_list_.front()); fec_packet_list_.pop_front(); @@ -637,9 +645,9 @@ void ForwardErrorCorrection::InsertPackets( bool ForwardErrorCorrection::InitRecovery(const FecPacket* fec_packet, RecoveredPacket* recovered) { // This is the first packet which we try to recover with. - const uint16_t ulp_header_size = - fec_packet->pkt->data[0] & 0x40 ? kUlpHeaderSizeLBitSet - : kUlpHeaderSizeLBitClear; // L bit set? + const uint16_t ulp_header_size = fec_packet->pkt->data[0] & 0x40 + ? kUlpHeaderSizeLBitSet + : kUlpHeaderSizeLBitClear; // L bit set? if (fec_packet->pkt->length < static_cast<size_t>(kFecHeaderSize + ulp_header_size)) { LOG(LS_WARNING) |