| Index: webrtc/modules/rtp_rtcp/source/forward_error_correction.h
|
| diff --git a/webrtc/modules/rtp_rtcp/source/forward_error_correction.h b/webrtc/modules/rtp_rtcp/source/forward_error_correction.h
|
| index 21f2afb2c00ec35e6129ee216737939a40630889..a0600f05bf5863f6c272596d20a3548dbbb216f3 100644
|
| --- a/webrtc/modules/rtp_rtcp/source/forward_error_correction.h
|
| +++ b/webrtc/modules/rtp_rtcp/source/forward_error_correction.h
|
| @@ -17,31 +17,32 @@
|
| #include <memory>
|
| #include <vector>
|
|
|
| +#include "webrtc/base/basictypes.h"
|
| +#include "webrtc/base/constructormagic.h"
|
| #include "webrtc/base/refcount.h"
|
| #include "webrtc/base/scoped_ref_ptr.h"
|
| #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
|
| #include "webrtc/modules/rtp_rtcp/source/forward_error_correction_internal.h"
|
| -#include "webrtc/typedefs.h"
|
|
|
| namespace webrtc {
|
|
|
| +class FecHeaderReader;
|
| +class FecHeaderWriter;
|
| +
|
| // Performs codec-independent forward error correction (FEC), based on RFC 5109.
|
| // Option exists to enable unequal protection (UEP) across packets.
|
| // This is not to be confused with protection within packets
|
| // (referred to as uneven level protection (ULP) in RFC 5109).
|
| class ForwardErrorCorrection {
|
| public:
|
| - // Maximum number of media packets we can protect
|
| - static constexpr size_t kMaxMediaPackets = 48u;
|
| -
|
| // TODO(holmer): As a next step all these struct-like packet classes should be
|
| // refactored into proper classes, and their members should be made private.
|
| // This will require parts of the functionality in forward_error_correction.cc
|
| // and receiver_fec.cc to be refactored into the packet classes.
|
| class Packet {
|
| public:
|
| - Packet() : length(0), data(), ref_count_(0) {}
|
| - virtual ~Packet() {}
|
| + Packet();
|
| + virtual ~Packet();
|
|
|
| // Add a reference.
|
| virtual int32_t AddRef();
|
| @@ -89,7 +90,7 @@ class ForwardErrorCorrection {
|
| rtc::scoped_refptr<Packet> pkt; // Pointer to the packet storage.
|
| };
|
|
|
| - // The recovered list parameter of #DecodeFec() references structs of
|
| + // The recovered list parameter of DecodeFec() references structs of
|
| // this type.
|
| // TODO(holmer): Refactor into a proper class.
|
| class RecoveredPacket : public SortablePacket {
|
| @@ -102,19 +103,55 @@ class ForwardErrorCorrection {
|
| // through the received packet list.
|
| bool returned; // True when the packet already has been returned to the
|
| // caller through the callback.
|
| - uint8_t length_recovery[2]; // Two bytes used for recovering the packet
|
| - // length with XOR operations.
|
| rtc::scoped_refptr<Packet> pkt; // Pointer to the packet storage.
|
| };
|
|
|
| + // Used to link media packets to their protecting FEC packets.
|
| + //
|
| + // TODO(holmer): Refactor into a proper class.
|
| + class ProtectedPacket : public ForwardErrorCorrection::SortablePacket {
|
| + public:
|
| + ProtectedPacket();
|
| + ~ProtectedPacket();
|
| +
|
| + rtc::scoped_refptr<ForwardErrorCorrection::Packet> pkt;
|
| + };
|
| +
|
| + using ProtectedPacketList = std::list<std::unique_ptr<ProtectedPacket>>;
|
| +
|
| + // Used for internal storage of received FEC packets in a list.
|
| + //
|
| + // TODO(holmer): Refactor into a proper class.
|
| + class ReceivedFecPacket : public ForwardErrorCorrection::SortablePacket {
|
| + public:
|
| + ReceivedFecPacket();
|
| + ~ReceivedFecPacket();
|
| +
|
| + // List of media packets that this FEC packet protects.
|
| + ProtectedPacketList protected_packets;
|
| + // RTP header fields.
|
| + uint32_t ssrc;
|
| + // FEC header fields.
|
| + size_t fec_header_size;
|
| + uint32_t protected_ssrc;
|
| + uint16_t seq_num_base;
|
| + size_t packet_mask_offset; // Relative start of FEC header.
|
| + size_t packet_mask_size;
|
| + size_t protection_length;
|
| + // Raw data.
|
| + rtc::scoped_refptr<ForwardErrorCorrection::Packet> pkt;
|
| + };
|
| +
|
| using PacketList = std::list<std::unique_ptr<Packet>>;
|
| using ReceivedPacketList = std::list<std::unique_ptr<ReceivedPacket>>;
|
| using RecoveredPacketList = std::list<std::unique_ptr<RecoveredPacket>>;
|
| + using ReceivedFecPacketList = std::list<std::unique_ptr<ReceivedFecPacket>>;
|
|
|
| - ForwardErrorCorrection();
|
| - virtual ~ForwardErrorCorrection();
|
| + ~ForwardErrorCorrection();
|
| +
|
| + // Creates a ForwardErrorCorrection tailored for a specific FEC scheme.
|
| + static std::unique_ptr<ForwardErrorCorrection> CreateUlpfec();
|
|
|
| - //
|
| // Generates a list of FEC packets from supplied media packets.
|
| //
|
| // Input: media_packets List of media packets to protect, of type
|
| @@ -158,7 +195,6 @@ class ForwardErrorCorrection {
|
| FecMaskType fec_mask_type,
|
| std::list<Packet*>* fec_packets);
|
|
|
| - //
|
| // 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
|
| @@ -198,47 +234,32 @@ class ForwardErrorCorrection {
|
| // Frees all memory allocated by this class.
|
| void ResetState(RecoveredPacketList* recovered_packets);
|
|
|
| - private:
|
| - // Used to link media packets to their protecting FEC packets.
|
| - //
|
| - // TODO(holmer): Refactor into a proper class.
|
| - class ProtectedPacket : public ForwardErrorCorrection::SortablePacket {
|
| - public:
|
| - rtc::scoped_refptr<ForwardErrorCorrection::Packet> pkt;
|
| - };
|
| -
|
| - using ProtectedPacketList = std::list<std::unique_ptr<ProtectedPacket>>;
|
| -
|
| - // Used for internal storage of received FEC packets in a list.
|
| - //
|
| - // TODO(holmer): Refactor into a proper class.
|
| - class ReceivedFecPacket : public ForwardErrorCorrection::SortablePacket {
|
| - public:
|
| - ProtectedPacketList protected_packets;
|
| - uint32_t ssrc; // SSRC of the current frame.
|
| - rtc::scoped_refptr<ForwardErrorCorrection::Packet> pkt;
|
| - };
|
| + // TODO(brandtr): Remove these functions when the Packet classes
|
| + // have been refactored.
|
| + static uint16_t ParseSequenceNumber(uint8_t* packet);
|
| + static uint32_t ParseSsrc(uint8_t* packet);
|
|
|
| - using ReceivedFecPacketList = std::list<std::unique_ptr<ReceivedFecPacket>>;
|
| + protected:
|
| + ForwardErrorCorrection(std::unique_ptr<FecHeaderReader> fec_header_reader,
|
| + std::unique_ptr<FecHeaderWriter> fec_header_writer);
|
|
|
| + private:
|
| // Analyzes |media_packets| for holes in the sequence and inserts zero columns
|
| // into the |packet_mask| where those holes are found. Zero columns means that
|
| // those packets will have no protection.
|
| // Returns the number of bits used for one row of the new packet mask.
|
| // Requires that |packet_mask| has at least 6 * |num_fec_packets| bytes
|
| // allocated.
|
| - int InsertZerosInBitMasks(const PacketList& media_packets,
|
| - uint8_t* packet_mask, int num_mask_bytes,
|
| - int num_fec_packets);
|
| -
|
| + int InsertZerosInPacketMasks(const PacketList& media_packets,
|
| + size_t num_fec_packets);
|
|
|
| - void GenerateFecUlpHeaders(const PacketList& media_packets,
|
| - uint8_t* packet_mask, int num_fec_packets,
|
| - bool l_bit);
|
| + // Writes FEC payloads and some recovery fields in the FEC headers.
|
| + void GenerateFecPayloads(const PacketList& media_packets,
|
| + size_t num_fec_packets);
|
|
|
| - void GenerateFecBitStrings(const PacketList& media_packets,
|
| - uint8_t* packet_mask, int num_fec_packets,
|
| - bool l_bit);
|
| + // Writes the FEC header fields that are not written by GenerateFecPayloads.
|
| + // This includes writing the packet masks.
|
| + void FinalizeFecHeaders(size_t num_fec_packets, uint16_t seq_num_base);
|
|
|
| // Inserts the |received_packets| into the internal received FEC packet list
|
| // or into |recovered_packets|.
|
| @@ -246,67 +267,145 @@ class ForwardErrorCorrection {
|
| RecoveredPacketList* recovered_packets);
|
|
|
| // Inserts the |received_packet| into |recovered_packets|. Deletes duplicates.
|
| - void InsertMediaPacket(ReceivedPacket* received_packet,
|
| - RecoveredPacketList* recovered_packets);
|
| + void InsertMediaPacket(RecoveredPacketList* recovered_packets,
|
| + ReceivedPacket* received_packet);
|
|
|
| // Assigns pointers to the recovered packet from all FEC packets which cover
|
| // it.
|
| // Note: This reduces the complexity when we want to try to recover a packet
|
| // since we don't have to find the intersection between recovered packets and
|
| // packets covered by the FEC packet.
|
| - void UpdateCoveringFecPackets(RecoveredPacket* packet);
|
| + void UpdateCoveringFecPackets(const RecoveredPacket& packet);
|
|
|
| // Insert |received_packet| into internal FEC list. Deletes duplicates.
|
| - void InsertFecPacket(ReceivedPacket* received_packet,
|
| - const RecoveredPacketList* recovered_packets);
|
| + void InsertFecPacket(const RecoveredPacketList& recovered_packets,
|
| + ReceivedPacket* received_packet);
|
|
|
| // Assigns pointers to already recovered packets covered by |fec_packet|.
|
| static void AssignRecoveredPackets(
|
| - ReceivedFecPacket* fec_packet,
|
| - const RecoveredPacketList* recovered_packets);
|
| -
|
| - // Insert |rec_packet_to_insert| into |recovered_packets| in correct position.
|
| - void InsertRecoveredPacket(RecoveredPacket* rec_packet_to_insert,
|
| - RecoveredPacketList* recovered_packets);
|
| + const RecoveredPacketList& recovered_packets,
|
| + ReceivedFecPacket* fec_packet);
|
|
|
| // Attempt to recover missing packets, using the internally stored
|
| // received FEC packets.
|
| - void AttemptRecover(RecoveredPacketList* recovered_packets);
|
| + void AttemptRecovery(RecoveredPacketList* recovered_packets);
|
|
|
| - // Initializes packet recovery using the received |fec_packet|.
|
| - static bool StartPacketRecovery(const ReceivedFecPacket* fec_packet,
|
| + // Initializes headers and payload before the XOR operation
|
| + // that recovers a packet.
|
| + static bool StartPacketRecovery(const ReceivedFecPacket& fec_packet,
|
| RecoveredPacket* recovered_packet);
|
|
|
| - // Performs XOR between |src| and |dst| and stores the result in |dst|.
|
| - static void XorPackets(const Packet* src, RecoveredPacket* dst);
|
| + // Performs XOR between the first 8 bytes of |src| and |dst| and stores
|
| + // the result in |dst|. The 3rd and 4th bytes are used for storing
|
| + // the length recovery field.
|
| + static void XorHeaders(const Packet& src, Packet* dst);
|
| +
|
| + // Performs XOR between the payloads of |src| and |dst| and stores the result
|
| + // in |dst|. The parameter |dst_offset| determines at what byte the
|
| + // XOR operation starts in |dst|. In total, |payload_length| bytes are XORed.
|
| + static void XorPayloads(const Packet& src,
|
| + size_t payload_length,
|
| + size_t dst_offset,
|
| + Packet* dst);
|
|
|
| - // Finish up the recovery of a packet.
|
| - static bool FinishPacketRecovery(RecoveredPacket* recovered_packet);
|
| + // Finalizes recovery of packet by setting RTP header fields.
|
| + // This is not specific to the FEC scheme used.
|
| + static bool FinishPacketRecovery(const ReceivedFecPacket& fec_packet,
|
| + RecoveredPacket* recovered_packet);
|
|
|
| // Recover a missing packet.
|
| - bool RecoverPacket(const ReceivedFecPacket* fec_packet,
|
| - RecoveredPacket* rec_packet_to_insert);
|
| + static bool RecoverPacket(const ReceivedFecPacket& fec_packet,
|
| + RecoveredPacket* recovered_packet);
|
|
|
| // 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);
|
| + 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);
|
| + void DiscardOldRecoveredPackets(RecoveredPacketList* recovered_packets);
|
| +
|
| + std::unique_ptr<FecHeaderReader> fec_header_reader_;
|
| + std::unique_ptr<FecHeaderWriter> fec_header_writer_;
|
|
|
| std::vector<Packet> generated_fec_packets_;
|
| ReceivedFecPacketList received_fec_packets_;
|
|
|
| // Arrays used to avoid dynamically allocating memory when generating
|
| - // the packet masks in the ULPFEC headers.
|
| - // (There are never more than |kMaxMediaPackets| FEC packets generated.)
|
| - uint8_t packet_mask_[kMaxMediaPackets * kMaskSizeLBitSet];
|
| - uint8_t tmp_packet_mask_[kMaxMediaPackets * kMaskSizeLBitSet];
|
| + // the packet masks.
|
| + // (There are never more than |kUlpfecMaxMediaPackets| FEC packets generated.)
|
| + uint8_t packet_masks_[kUlpfecMaxMediaPackets * kUlpfecMaxPacketMaskSize];
|
| + uint8_t tmp_packet_masks_[kUlpfecMaxMediaPackets * kUlpfecMaxPacketMaskSize];
|
| + size_t packet_mask_size_;
|
| };
|
| +
|
| +// Classes derived from FecHeader{Reader,Writer} encapsulate the
|
| +// specifics of reading and writing FEC header for, e.g., ULPFEC
|
| +// and FlexFEC.
|
| +class FecHeaderReader {
|
| + public:
|
| + virtual ~FecHeaderReader();
|
| +
|
| + // The maximum number of media packets that can be covered by one FEC packet.
|
| + size_t MaxMediaPackets() const;
|
| +
|
| + // The maximum number of FEC packets that is supported, per call
|
| + // to ForwardErrorCorrection::EncodeFec().
|
| + size_t MaxFecPackets() const;
|
| +
|
| + // Parses FEC header and stores information in ReceivedFecPacket members.
|
| + virtual bool ReadFecHeader(
|
| + ForwardErrorCorrection::ReceivedFecPacket* fec_packet) const = 0;
|
| +
|
| + protected:
|
| + FecHeaderReader(size_t max_media_packets, size_t max_fec_packets);
|
| +
|
| + const size_t max_media_packets_;
|
| + const size_t max_fec_packets_;
|
| +};
|
| +
|
| +class FecHeaderWriter {
|
| + public:
|
| + virtual ~FecHeaderWriter();
|
| +
|
| + // The maximum number of media packets that can be covered by one FEC packet.
|
| + size_t MaxMediaPackets() const;
|
| +
|
| + // The maximum number of FEC packets that is supported, per call
|
| + // to ForwardErrorCorrection::EncodeFec().
|
| + size_t MaxFecPackets() const;
|
| +
|
| + // The maximum overhead (in bytes) per packet, due to FEC headers.
|
| + size_t MaxPacketOverhead() const;
|
| +
|
| + // Calculates the minimum packet mask size needed (in bytes),
|
| + // given the discrete options of the ULPFEC masks and the bits
|
| + // set in the current packet mask.
|
| + virtual size_t MinPacketMaskSize(const uint8_t* packet_mask,
|
| + size_t packet_mask_size) const = 0;
|
| +
|
| + // The header size (in bytes), given the packet mask size.
|
| + virtual size_t FecHeaderSize(size_t packet_mask_size) const = 0;
|
| +
|
| + // Writes FEC header.
|
| + virtual void FinalizeFecHeader(
|
| + uint16_t seq_num_base,
|
| + const uint8_t* packet_mask,
|
| + size_t packet_mask_size,
|
| + ForwardErrorCorrection::Packet* fec_packet) const = 0;
|
| +
|
| + protected:
|
| + FecHeaderWriter(size_t max_media_packets,
|
| + size_t max_fec_packets,
|
| + size_t max_packet_overhead);
|
| +
|
| + const size_t max_media_packets_;
|
| + const size_t max_fec_packets_;
|
| + const size_t max_packet_overhead_;
|
| +};
|
| +
|
| } // namespace webrtc
|
| +
|
| #endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_FORWARD_ERROR_CORRECTION_H_
|
|
|