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