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_ |