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