Chromium Code Reviews| 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..e4986389e2b02187404da66f61b46c3ffdbcfeb8 100644 |
| --- a/webrtc/modules/rtp_rtcp/source/forward_error_correction.h |
| +++ b/webrtc/modules/rtp_rtcp/source/forward_error_correction.h |
| @@ -14,26 +14,29 @@ |
| #include <stdint.h> |
| #include <list> |
| +#include <map> |
| #include <memory> |
| +#include <tuple> |
| #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 |
| @@ -79,9 +82,6 @@ class ForwardErrorCorrection { |
| // TODO(holmer): Refactor into a proper class. |
| class ReceivedPacket : public SortablePacket { |
| public: |
| - ReceivedPacket(); |
|
danilchap
2016/08/24 10:42:40
what is motiviation for removing constructor/destr
brandtr
2016/08/24 11:34:23
Re-adding non-inlined default constructor, as per
danilchap
2016/08/24 16:41:26
yes. POD = Plain Old Data (http://en.cppreference.
|
| - ~ReceivedPacket(); |
| - |
| uint32_t ssrc; // SSRC of the current frame. Must be set for FEC |
| // packets, but not required for media packets. |
| bool is_fec; // Set to true if this is an FEC packet and false |
| @@ -89,32 +89,55 @@ 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 { |
| public: |
| - RecoveredPacket(); |
|
danilchap
2016/08/24 10:42:40
same here.
brandtr
2016/08/24 11:34:24
Done.
|
| - ~RecoveredPacket(); |
| - |
| bool was_recovered; // Will be true if this packet was recovered by |
| // the FEC. Otherwise it was a media packet passed in |
| // 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: |
| + 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; |
| + // RTP header fields. |
| + uint32_t rtp_ssrc; |
| + // FEC header fields. |
| + size_t fec_header_size; |
| + size_t protection_length; |
| + // Packet masks metadata. |
| + // SSRC -> [SN base, packet mask offset, packet mask size (bytes)] |
|
danilchap
2016/08/24 10:42:40
probably clearer instead of two comments have a he
brandtr
2016/08/24 11:34:24
Good idea, done!
|
| + std::map<uint32_t, std::tuple<uint16_t, size_t, size_t>> packet_mask_info; |
| + // 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(); |
| + // 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 +181,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 +220,34 @@ 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: |
| + // This constructor is used by the unit tests. |
| + 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); |
| + // Writes FEC payload and some recovery fields in the FEC headers. |
| + void GenerateFecPayloads(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); |
| - |
| - 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(const PacketList& media_packets, |
| + size_t num_fec_packets); |
| // Inserts the |received_packets| into the internal received FEC packet list |
| // or into |recovered_packets|. |
| @@ -265,27 +274,33 @@ class ForwardErrorCorrection { |
| 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); |
| - |
| // Attempt to recover missing packets, using the internally stored |
| // received FEC packets. |
| - void AttemptRecover(RecoveredPacketList* recovered_packets); |
| - |
| - // Initializes packet recovery using the received |fec_packet|. |
| - static bool StartPacketRecovery(const ReceivedFecPacket* fec_packet, |
| - RecoveredPacket* recovered_packet); |
| + void AttemptRecovery(RecoveredPacketList* recovered_packets); |
| // 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_packet); |
| + // The parameters |src_offset| and |dst_offset| determines at what byte |
| + // the XOR operation starts in |src| and |dst|, respectively. In total, |
| + // |payload_length| bytes are XORed. |
| + static void XorPackets(const Packet* src, |
| + size_t src_offset, |
| + size_t payload_length, |
| + size_t dst_offset, |
| + Packet* dst); |
| + |
| + // Initializes headers and payload before the XOR operation |
| + // that recovers a packet. |
| + bool StartPacketRecovery(ReceivedFecPacket* fec_packet, |
| + RecoveredPacket* recovered_packet) const; |
| + |
| + // 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); |
| + bool RecoverPacket(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 |
| @@ -295,18 +310,89 @@ class ForwardErrorCorrection { |
| // 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 * kUlpfecPacketMaskSizeLBitSet]; |
| + uint8_t |
| + tmp_packet_masks_[kUlpfecMaxMediaPackets * kUlpfecPacketMaskSizeLBitSet]; |
| + 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: |
| + FecHeaderWriter(size_t max_media_packets, size_t max_fec_packets); |
| + 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( |
| + const ForwardErrorCorrection::PacketList& media_packets, |
| + 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_ |