1 /* 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #ifndef MODULES_RTP_RTCP_SOURCE_FORWARD_ERROR_CORRECTION_H_ 12 #define MODULES_RTP_RTCP_SOURCE_FORWARD_ERROR_CORRECTION_H_ 13 14 #include <stddef.h> 15 #include <stdint.h> 16 17 #include <list> 18 #include <memory> 19 #include <vector> 20 21 #include "api/scoped_refptr.h" 22 #include "modules/include/module_fec_types.h" 23 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" 24 #include "modules/rtp_rtcp/source/forward_error_correction_internal.h" 25 #include "rtc_base/copy_on_write_buffer.h" 26 27 namespace webrtc { 28 29 class FecHeaderReader; 30 class FecHeaderWriter; 31 32 // Performs codec-independent forward error correction (FEC), based on RFC 5109. 33 // Option exists to enable unequal protection (UEP) across packets. 34 // This is not to be confused with protection within packets 35 // (referred to as uneven level protection (ULP) in RFC 5109). 36 // TODO(brandtr): Split this class into a separate encoder 37 // and a separate decoder. 38 class ForwardErrorCorrection { 39 public: 40 // TODO(holmer): As a next step all these struct-like packet classes should be 41 // refactored into proper classes, and their members should be made private. 42 // This will require parts of the functionality in forward_error_correction.cc 43 // and receiver_fec.cc to be refactored into the packet classes. 44 class Packet { 45 public: 46 Packet(); 47 virtual ~Packet(); 48 49 // Add a reference. 50 virtual int32_t AddRef(); 51 52 // Release a reference. Will delete the object if the reference count 53 // reaches zero. 54 virtual int32_t Release(); 55 56 rtc::CopyOnWriteBuffer data; // Packet data. 57 58 private: 59 int32_t ref_count_; // Counts the number of references to a packet. 60 }; 61 62 // TODO(holmer): Refactor into a proper class. 63 class SortablePacket { 64 public: 65 // Functor which returns true if the sequence number of |first| 66 // is < the sequence number of |second|. Should only ever be called for 67 // packets belonging to the same SSRC. 68 struct LessThan { 69 template <typename S, typename T> 70 bool operator()(const S& first, const T& second); 71 }; 72 73 uint32_t ssrc; 74 uint16_t seq_num; 75 }; 76 77 // Used for the input to DecodeFec(). 78 // 79 // TODO(nisse): Delete class, instead passing |is_fec| and |pkt| as separate 80 // arguments. 81 class ReceivedPacket : public SortablePacket { 82 public: 83 ReceivedPacket(); 84 ~ReceivedPacket(); 85 86 bool is_fec; // Set to true if this is an FEC packet and false 87 // otherwise. 88 bool is_recovered; 89 rtc::scoped_refptr<Packet> pkt; // Pointer to the packet storage. 90 }; 91 92 // The recovered list parameter of DecodeFec() references structs of 93 // this type. 94 // TODO(holmer): Refactor into a proper class. 95 class RecoveredPacket : public SortablePacket { 96 public: 97 RecoveredPacket(); 98 ~RecoveredPacket(); 99 100 bool was_recovered; // Will be true if this packet was recovered by 101 // the FEC. Otherwise it was a media packet passed in 102 // through the received packet list. 103 bool returned; // True when the packet already has been returned to the 104 // caller through the callback. 105 rtc::scoped_refptr<Packet> pkt; // Pointer to the packet storage. 106 }; 107 108 // Used to link media packets to their protecting FEC packets. 109 // 110 // TODO(holmer): Refactor into a proper class. 111 class ProtectedPacket : public SortablePacket { 112 public: 113 ProtectedPacket(); 114 ~ProtectedPacket(); 115 116 rtc::scoped_refptr<ForwardErrorCorrection::Packet> pkt; 117 }; 118 119 using ProtectedPacketList = std::list<std::unique_ptr<ProtectedPacket>>; 120 121 // Used for internal storage of received FEC packets in a list. 122 // 123 // TODO(holmer): Refactor into a proper class. 124 class ReceivedFecPacket : public SortablePacket { 125 public: 126 ReceivedFecPacket(); 127 ~ReceivedFecPacket(); 128 129 // List of media packets that this FEC packet protects. 130 ProtectedPacketList protected_packets; 131 // RTP header fields. 132 uint32_t ssrc; 133 // FEC header fields. 134 size_t fec_header_size; 135 uint32_t protected_ssrc; 136 uint16_t seq_num_base; 137 size_t packet_mask_offset; // Relative start of FEC header. 138 size_t packet_mask_size; 139 size_t protection_length; 140 // Raw data. 141 rtc::scoped_refptr<ForwardErrorCorrection::Packet> pkt; 142 }; 143 144 using PacketList = std::list<std::unique_ptr<Packet>>; 145 using RecoveredPacketList = std::list<std::unique_ptr<RecoveredPacket>>; 146 using ReceivedFecPacketList = std::list<std::unique_ptr<ReceivedFecPacket>>; 147 148 ~ForwardErrorCorrection(); 149 150 // Creates a ForwardErrorCorrection tailored for a specific FEC scheme. 151 static std::unique_ptr<ForwardErrorCorrection> CreateUlpfec(uint32_t ssrc); 152 static std::unique_ptr<ForwardErrorCorrection> CreateFlexfec( 153 uint32_t ssrc, 154 uint32_t protected_media_ssrc); 155 156 // Generates a list of FEC packets from supplied media packets. 157 // 158 // Input: media_packets List of media packets to protect, of type 159 // Packet. All packets must belong to the 160 // same frame and the list must not be empty. 161 // Input: protection_factor FEC protection overhead in the [0, 255] 162 // domain. To obtain 100% overhead, or an 163 // equal number of FEC packets as 164 // media packets, use 255. 165 // Input: num_important_packets The number of "important" packets in the 166 // frame. These packets may receive greater 167 // protection than the remaining packets. 168 // The important packets must be located at the 169 // start of the media packet list. For codecs 170 // with data partitioning, the important 171 // packets may correspond to first partition 172 // packets. 173 // Input: use_unequal_protection Parameter to enable/disable unequal 174 // protection (UEP) across packets. Enabling 175 // UEP will allocate more protection to the 176 // num_important_packets from the start of the 177 // media_packets. 178 // Input: fec_mask_type The type of packet mask used in the FEC. 179 // Random or bursty type may be selected. The 180 // bursty type is only defined up to 12 media 181 // packets. If the number of media packets is 182 // above 12, the packet masks from the random 183 // table will be selected. 184 // Output: fec_packets List of pointers to generated FEC packets, 185 // of type Packet. Must be empty on entry. 186 // The memory available through the list will 187 // be valid until the next call to 188 // EncodeFec(). 189 // 190 // Returns 0 on success, -1 on failure. 191 // 192 int EncodeFec(const PacketList& media_packets, 193 uint8_t protection_factor, 194 int num_important_packets, 195 bool use_unequal_protection, 196 FecMaskType fec_mask_type, 197 std::list<Packet*>* fec_packets); 198 199 // Decodes a list of received media and FEC packets. It will parse the 200 // |received_packets|, storing FEC packets internally, and move 201 // media packets to |recovered_packets|. The recovered list will be 202 // sorted by ascending sequence number and have duplicates removed. 203 // The function should be called as new packets arrive, and 204 // |recovered_packets| will be progressively assembled with each call. 205 // When the function returns, |received_packets| will be empty. 206 // 207 // The caller will allocate packets submitted through |received_packets|. 208 // The function will handle allocation of recovered packets. 209 // 210 // Input: received_packets List of new received packets, of type 211 // ReceivedPacket, belonging to a single 212 // frame. At output the list will be empty, 213 // with packets either stored internally, 214 // or accessible through the recovered list. 215 // Output: recovered_packets List of recovered media packets, of type 216 // RecoveredPacket, belonging to a single 217 // frame. The memory available through the 218 // list will be valid until the next call to 219 // DecodeFec(). 220 // 221 void DecodeFec(const ReceivedPacket& received_packet, 222 RecoveredPacketList* recovered_packets); 223 224 // Get the number of generated FEC packets, given the number of media packets 225 // and the protection factor. 226 static int NumFecPackets(int num_media_packets, int protection_factor); 227 228 // Gets the maximum size of the FEC headers in bytes, which must be 229 // accounted for as packet overhead. 230 size_t MaxPacketOverhead() const; 231 232 // Reset internal states from last frame and clear |recovered_packets|. 233 // Frees all memory allocated by this class. 234 void ResetState(RecoveredPacketList* recovered_packets); 235 236 // TODO(brandtr): Remove these functions when the Packet classes 237 // have been refactored. 238 static uint16_t ParseSequenceNumber(uint8_t* packet); 239 static uint32_t ParseSsrc(uint8_t* packet); 240 241 protected: 242 ForwardErrorCorrection(std::unique_ptr<FecHeaderReader> fec_header_reader, 243 std::unique_ptr<FecHeaderWriter> fec_header_writer, 244 uint32_t ssrc, 245 uint32_t protected_media_ssrc); 246 247 private: 248 // Analyzes |media_packets| for holes in the sequence and inserts zero columns 249 // into the |packet_mask| where those holes are found. Zero columns means that 250 // those packets will have no protection. 251 // Returns the number of bits used for one row of the new packet mask. 252 // Requires that |packet_mask| has at least 6 * |num_fec_packets| bytes 253 // allocated. 254 int InsertZerosInPacketMasks(const PacketList& media_packets, 255 size_t num_fec_packets); 256 257 // Writes FEC payloads and some recovery fields in the FEC headers. 258 void GenerateFecPayloads(const PacketList& media_packets, 259 size_t num_fec_packets); 260 261 // Writes the FEC header fields that are not written by GenerateFecPayloads. 262 // This includes writing the packet masks. 263 void FinalizeFecHeaders(size_t num_fec_packets, 264 uint32_t media_ssrc, 265 uint16_t seq_num_base); 266 267 // Inserts the |received_packet| into the internal received FEC packet list 268 // or into |recovered_packets|. 269 void InsertPacket(const ReceivedPacket& received_packet, 270 RecoveredPacketList* recovered_packets); 271 272 // Inserts the |received_packet| into |recovered_packets|. Deletes duplicates. 273 void InsertMediaPacket(RecoveredPacketList* recovered_packets, 274 const ReceivedPacket& received_packet); 275 276 // Assigns pointers to the recovered packet from all FEC packets which cover 277 // it. 278 // Note: This reduces the complexity when we want to try to recover a packet 279 // since we don't have to find the intersection between recovered packets and 280 // packets covered by the FEC packet. 281 void UpdateCoveringFecPackets(const RecoveredPacket& packet); 282 283 // Insert |received_packet| into internal FEC list. Deletes duplicates. 284 void InsertFecPacket(const RecoveredPacketList& recovered_packets, 285 const ReceivedPacket& received_packet); 286 287 // Assigns pointers to already recovered packets covered by |fec_packet|. 288 static void AssignRecoveredPackets( 289 const RecoveredPacketList& recovered_packets, 290 ReceivedFecPacket* fec_packet); 291 292 // Attempt to recover missing packets, using the internally stored 293 // received FEC packets. 294 void AttemptRecovery(RecoveredPacketList* recovered_packets); 295 296 // Initializes headers and payload before the XOR operation 297 // that recovers a packet. 298 static bool StartPacketRecovery(const ReceivedFecPacket& fec_packet, 299 RecoveredPacket* recovered_packet); 300 301 // Performs XOR between the first 8 bytes of |src| and |dst| and stores 302 // the result in |dst|. The 3rd and 4th bytes are used for storing 303 // the length recovery field. 304 static void XorHeaders(const Packet& src, Packet* dst); 305 306 // Performs XOR between the payloads of |src| and |dst| and stores the result 307 // in |dst|. The parameter |dst_offset| determines at what byte the 308 // XOR operation starts in |dst|. In total, |payload_length| bytes are XORed. 309 static void XorPayloads(const Packet& src, 310 size_t payload_length, 311 size_t dst_offset, 312 Packet* dst); 313 314 // Finalizes recovery of packet by setting RTP header fields. 315 // This is not specific to the FEC scheme used. 316 static bool FinishPacketRecovery(const ReceivedFecPacket& fec_packet, 317 RecoveredPacket* recovered_packet); 318 319 // Recover a missing packet. 320 static bool RecoverPacket(const ReceivedFecPacket& fec_packet, 321 RecoveredPacket* recovered_packet); 322 323 // Get the number of missing media packets which are covered by |fec_packet|. 324 // An FEC packet can recover at most one packet, and if zero packets are 325 // missing the FEC packet can be discarded. This function returns 2 when two 326 // or more packets are missing. 327 static int NumCoveredPacketsMissing(const ReceivedFecPacket& fec_packet); 328 329 // Discards old packets in |recovered_packets|, which are no longer relevant 330 // for recovering lost packets. 331 void DiscardOldRecoveredPackets(RecoveredPacketList* recovered_packets); 332 333 // These SSRCs are only used by the decoder. 334 const uint32_t ssrc_; 335 const uint32_t protected_media_ssrc_; 336 337 std::unique_ptr<FecHeaderReader> fec_header_reader_; 338 std::unique_ptr<FecHeaderWriter> fec_header_writer_; 339 340 std::vector<Packet> generated_fec_packets_; 341 ReceivedFecPacketList received_fec_packets_; 342 343 // Arrays used to avoid dynamically allocating memory when generating 344 // the packet masks. 345 // (There are never more than |kUlpfecMaxMediaPackets| FEC packets generated.) 346 uint8_t packet_masks_[kUlpfecMaxMediaPackets * kUlpfecMaxPacketMaskSize]; 347 uint8_t tmp_packet_masks_[kUlpfecMaxMediaPackets * kUlpfecMaxPacketMaskSize]; 348 size_t packet_mask_size_; 349 }; 350 351 // Classes derived from FecHeader{Reader,Writer} encapsulate the 352 // specifics of reading and writing FEC header for, e.g., ULPFEC 353 // and FlexFEC. 354 class FecHeaderReader { 355 public: 356 virtual ~FecHeaderReader(); 357 358 // The maximum number of media packets that can be covered by one FEC packet. 359 size_t MaxMediaPackets() const; 360 361 // The maximum number of FEC packets that is supported, per call 362 // to ForwardErrorCorrection::EncodeFec(). 363 size_t MaxFecPackets() const; 364 365 // Parses FEC header and stores information in ReceivedFecPacket members. 366 virtual bool ReadFecHeader( 367 ForwardErrorCorrection::ReceivedFecPacket* fec_packet) const = 0; 368 369 protected: 370 FecHeaderReader(size_t max_media_packets, size_t max_fec_packets); 371 372 const size_t max_media_packets_; 373 const size_t max_fec_packets_; 374 }; 375 376 class FecHeaderWriter { 377 public: 378 virtual ~FecHeaderWriter(); 379 380 // The maximum number of media packets that can be covered by one FEC packet. 381 size_t MaxMediaPackets() const; 382 383 // The maximum number of FEC packets that is supported, per call 384 // to ForwardErrorCorrection::EncodeFec(). 385 size_t MaxFecPackets() const; 386 387 // The maximum overhead (in bytes) per packet, due to FEC headers. 388 size_t MaxPacketOverhead() const; 389 390 // Calculates the minimum packet mask size needed (in bytes), 391 // given the discrete options of the ULPFEC masks and the bits 392 // set in the current packet mask. 393 virtual size_t MinPacketMaskSize(const uint8_t* packet_mask, 394 size_t packet_mask_size) const = 0; 395 396 // The header size (in bytes), given the packet mask size. 397 virtual size_t FecHeaderSize(size_t packet_mask_size) const = 0; 398 399 // Writes FEC header. 400 virtual void FinalizeFecHeader( 401 uint32_t media_ssrc, 402 uint16_t seq_num_base, 403 const uint8_t* packet_mask, 404 size_t packet_mask_size, 405 ForwardErrorCorrection::Packet* fec_packet) const = 0; 406 407 protected: 408 FecHeaderWriter(size_t max_media_packets, 409 size_t max_fec_packets, 410 size_t max_packet_overhead); 411 412 const size_t max_media_packets_; 413 const size_t max_fec_packets_; 414 const size_t max_packet_overhead_; 415 }; 416 417 } // namespace webrtc 418 419 #endif // MODULES_RTP_RTCP_SOURCE_FORWARD_ERROR_CORRECTION_H_ 420