xref: /aosp_15_r20/external/webrtc/modules/rtp_rtcp/source/forward_error_correction.h (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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