OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_FORWARD_ERROR_CORRECTION_H_ | 11 #ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_FORWARD_ERROR_CORRECTION_H_ |
12 #define WEBRTC_MODULES_RTP_RTCP_SOURCE_FORWARD_ERROR_CORRECTION_H_ | 12 #define WEBRTC_MODULES_RTP_RTCP_SOURCE_FORWARD_ERROR_CORRECTION_H_ |
13 | 13 |
14 #include <stdint.h> | 14 #include <stdint.h> |
15 | 15 |
16 #include <list> | 16 #include <list> |
17 #include <memory> | |
17 #include <vector> | 18 #include <vector> |
18 | 19 |
19 #include "webrtc/base/refcount.h" | 20 #include "webrtc/base/refcount.h" |
20 #include "webrtc/base/scoped_ref_ptr.h" | 21 #include "webrtc/base/scoped_ref_ptr.h" |
21 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" | 22 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" |
22 #include "webrtc/modules/rtp_rtcp/source/forward_error_correction_internal.h" | 23 #include "webrtc/modules/rtp_rtcp/source/forward_error_correction_internal.h" |
23 #include "webrtc/typedefs.h" | 24 #include "webrtc/typedefs.h" |
24 | 25 |
25 namespace webrtc { | 26 namespace webrtc { |
26 | 27 |
27 // Forward declaration. | |
28 class FecPacket; | |
29 | |
30 // Performs codec-independent forward error correction (FEC), based on RFC 5109. | 28 // Performs codec-independent forward error correction (FEC), based on RFC 5109. |
31 // Option exists to enable unequal protection (UEP) across packets. | 29 // Option exists to enable unequal protection (UEP) across packets. |
32 // This is not to be confused with protection within packets | 30 // This is not to be confused with protection within packets |
33 // (referred to as uneven level protection (ULP) in RFC 5109). | 31 // (referred to as uneven level protection (ULP) in RFC 5109). |
34 class ForwardErrorCorrection { | 32 class ForwardErrorCorrection { |
35 public: | 33 public: |
36 // Maximum number of media packets we can protect | 34 // Maximum number of media packets we can protect |
37 static constexpr size_t kMaxMediaPackets = 48u; | 35 static constexpr size_t kMaxMediaPackets = 48u; |
38 | 36 |
39 // TODO(holmer): As a next step all these struct-like packet classes should be | 37 // TODO(holmer): As a next step all these struct-like packet classes should be |
(...skipping 15 matching lines...) Expand all Loading... | |
55 size_t length; // Length of packet in bytes. | 53 size_t length; // Length of packet in bytes. |
56 uint8_t data[IP_PACKET_SIZE]; // Packet data. | 54 uint8_t data[IP_PACKET_SIZE]; // Packet data. |
57 | 55 |
58 private: | 56 private: |
59 int32_t ref_count_; // Counts the number of references to a packet. | 57 int32_t ref_count_; // Counts the number of references to a packet. |
60 }; | 58 }; |
61 | 59 |
62 // TODO(holmer): Refactor into a proper class. | 60 // TODO(holmer): Refactor into a proper class. |
63 class SortablePacket { | 61 class SortablePacket { |
64 public: | 62 public: |
65 // True if first is <= than second. | 63 // Functor which returns true if the sequence number of |first| |
66 static bool LessThan(const SortablePacket* first, | 64 // is < the sequence number of |second|. |
67 const SortablePacket* second); | 65 struct LessThan { |
66 template <typename S, typename T> | |
67 bool operator() (const S& first, const T& second); | |
stefan-webrtc
2016/08/01 11:29:51
This should be static, right?
danilchap
2016/08/01 13:29:07
it wouldn't compile:
error: overloaded 'operator()
stefan-webrtc
2016/08/01 14:33:23
Good point. But maybe we can make it a static func
| |
68 }; | |
68 | 69 |
69 uint16_t seq_num; | 70 uint16_t seq_num; |
70 }; | 71 }; |
71 | 72 |
72 // The received list parameter of #DecodeFec() must reference structs of this | 73 // The received list parameter of #DecodeFec() must reference structs of this |
73 // type. The last_media_pkt_in_frame is not required to be used for correct | 74 // type. The last_media_pkt_in_frame is not required to be used for correct |
74 // recovery, but will reduce delay by allowing #DecodeFec() to pre-emptively | 75 // recovery, but will reduce delay by allowing #DecodeFec() to pre-emptively |
75 // determine frame completion. If set, we assume a FEC stream, and the | 76 // determine frame completion. If set, we assume a FEC stream, and the |
76 // following assumptions must hold: | 77 // following assumptions must hold: |
77 // | 78 // |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
109 bool was_recovered; // Will be true if this packet was recovered by | 110 bool was_recovered; // Will be true if this packet was recovered by |
110 // the FEC. Otherwise it was a media packet passed in | 111 // the FEC. Otherwise it was a media packet passed in |
111 // through the received packet list. | 112 // through the received packet list. |
112 bool returned; // True when the packet already has been returned to the | 113 bool returned; // True when the packet already has been returned to the |
113 // caller through the callback. | 114 // caller through the callback. |
114 uint8_t length_recovery[2]; // Two bytes used for recovering the packet | 115 uint8_t length_recovery[2]; // Two bytes used for recovering the packet |
115 // length with XOR operations. | 116 // length with XOR operations. |
116 rtc::scoped_refptr<Packet> pkt; // Pointer to the packet storage. | 117 rtc::scoped_refptr<Packet> pkt; // Pointer to the packet storage. |
117 }; | 118 }; |
118 | 119 |
119 typedef std::list<Packet*> PacketList; | 120 using PacketList = std::list<std::unique_ptr<Packet>>; |
120 typedef std::list<ReceivedPacket*> ReceivedPacketList; | 121 using ReceivedPacketList = std::list<std::unique_ptr<ReceivedPacket>>; |
121 typedef std::list<RecoveredPacket*> RecoveredPacketList; | 122 using RecoveredPacketList = std::list<std::unique_ptr<RecoveredPacket>>; |
122 | 123 |
123 ForwardErrorCorrection(); | 124 ForwardErrorCorrection(); |
124 virtual ~ForwardErrorCorrection(); | 125 virtual ~ForwardErrorCorrection(); |
125 | 126 |
126 /** | 127 /** |
127 * Generates a list of FEC packets from supplied media packets. | 128 * Generates a list of FEC packets from supplied media packets. |
128 * | 129 * |
129 * \param[in] mediaPacketList List of media packets to protect, of type | 130 * \param[in] mediaPacketList List of media packets to protect, of type |
130 * #Packet. All packets must belong to the | 131 * #Packet. All packets must belong to the |
131 * same frame and the list must not be empty. | 132 * same frame and the list must not be empty. |
(...skipping 20 matching lines...) Expand all Loading... | |
152 * packets. If the number of media packets is | 153 * packets. If the number of media packets is |
153 * above 12, the packets masks from the | 154 * above 12, the packets masks from the |
154 * random table will be selected. | 155 * random table will be selected. |
155 * \param[out] fecPacketList List of FEC packets, of type #Packet. Must | 156 * \param[out] fecPacketList List of FEC packets, of type #Packet. Must |
156 * be empty on entry. The memory available | 157 * be empty on entry. The memory available |
157 * through the list will be valid until the | 158 * through the list will be valid until the |
158 * next call to GenerateFec(). | 159 * next call to GenerateFec(). |
159 * | 160 * |
160 * \return 0 on success, -1 on failure. | 161 * \return 0 on success, -1 on failure. |
161 */ | 162 */ |
162 int GenerateFec(const PacketList& media_packet_list, | 163 int GenerateFec(const PacketList& media_packets, |
163 uint8_t protection_factor, int num_important_packets, | 164 uint8_t protection_factor, int num_important_packets, |
164 bool use_unequal_protection, FecMaskType fec_mask_type, | 165 bool use_unequal_protection, FecMaskType fec_mask_type, |
165 PacketList* fec_packet_list); | 166 std::list<Packet*>* fec_packets); |
166 | 167 |
167 /** | 168 /** |
168 * Decodes a list of media and FEC packets. It will parse the input received | 169 * Decodes a list of media and FEC packets. It will parse the input received |
169 * packet list, storing FEC packets internally and inserting media packets to | 170 * packet list, storing FEC packets internally and inserting media packets to |
170 * the output recovered packet list. The recovered list will be sorted by | 171 * the output recovered packet list. The recovered list will be sorted by |
171 * ascending sequence number and have duplicates removed. The function | 172 * ascending sequence number and have duplicates removed. The function |
172 * should be called as new packets arrive, with the recovered list being | 173 * should be called as new packets arrive, with the recovered list being |
173 * progressively assembled with each call. The received packet list will be | 174 * progressively assembled with each call. The received packet list will be |
174 * empty at output. | 175 * empty at output. |
175 * | 176 * |
176 * The user will allocate packets submitted through the received list. The | 177 * The user will allocate packets submitted through the received list. The |
177 * function will handle allocation of recovered packets and optionally | 178 * function will handle allocation of recovered packets and optionally |
178 * deleting of all packet memory. The user may delete the recovered list | 179 * deleting of all packet memory. The user may delete the recovered list |
179 * packets, in which case they must remove deleted packets from the | 180 * packets, in which case they must remove deleted packets from the |
180 * recovered list. | 181 * recovered list. |
181 * | 182 * |
182 * \param[in] receivedPacketList List of new received packets, of type | 183 * \param[in] receivedPacketList List of new received packets, of type |
183 * #ReceivedPacket, belonging to a single | 184 * #ReceivedPacket, belonging to a single |
184 * frame. At output the list will be empty, | 185 * frame. At output the list will be empty, |
185 * with packets either stored internally, | 186 * with packets either stored internally, |
186 * or accessible through the recovered list. | 187 * or accessible through the recovered list. |
187 * \param[out] recoveredPacketList List of recovered media packets, of type | 188 * \param[out] recoveredPacketList List of recovered media packets, of type |
188 * #RecoveredPacket, belonging to a single | 189 * #RecoveredPacket, belonging to a single |
189 * frame. The memory available through the | 190 * frame. The memory available through the |
190 * list will be valid until the next call to | 191 * list will be valid until the next call to |
191 * DecodeFec(). | 192 * DecodeFec(). |
192 * | 193 * |
193 * \return 0 on success, -1 on failure. | 194 * \return 0 on success, -1 on failure. |
194 */ | 195 */ |
195 int DecodeFec(ReceivedPacketList* received_packet_list, | 196 int DecodeFec(ReceivedPacketList* received_packets, |
196 RecoveredPacketList* recovered_packet_list); | 197 RecoveredPacketList* recovered_packets); |
197 | 198 |
198 // Get the number of FEC packets, given the number of media packets and the | 199 // Get the number of FEC packets, given the number of media packets and the |
199 // protection factor. | 200 // protection factor. |
200 int GetNumberOfFecPackets(int num_media_packets, int protection_factor); | 201 int GetNumberOfFecPackets(int num_media_packets, int protection_factor); |
201 | 202 |
202 // Gets the size in bytes of the FEC/ULP headers, which must be accounted for | 203 // Gets the size in bytes of the FEC/ULP headers, which must be accounted for |
203 // as packet overhead. | 204 // as packet overhead. |
204 // \return Packet overhead in bytes. | 205 // \return Packet overhead in bytes. |
205 static size_t PacketOverhead(); | 206 static size_t PacketOverhead(); |
206 | 207 |
207 // Reset internal states from last frame and clear the recovered_packet_list. | 208 // Reset internal states from last frame and clears |recovered_packets|. |
208 // Frees all memory allocated by this class. | 209 // Frees all memory allocated by this class. |
209 void ResetState(RecoveredPacketList* recovered_packet_list); | 210 void ResetState(RecoveredPacketList* recovered_packets); |
210 | 211 |
211 private: | 212 private: |
212 typedef std::list<FecPacket*> FecPacketList; | 213 // Used to link media packets to their protecting FEC packets. |
214 // | |
215 // TODO(holmer): Refactor into a proper class. | |
216 class ProtectedPacket : public ForwardErrorCorrection::SortablePacket { | |
217 public: | |
218 rtc::scoped_refptr<ForwardErrorCorrection::Packet> pkt; | |
219 }; | |
220 | |
221 using ProtectedPacketList = std::list<std::unique_ptr<ProtectedPacket>>; | |
222 | |
223 // Used for internal storage of received FEC packets in a list. | |
224 // | |
225 // TODO(holmer): Refactor into a proper class. | |
226 class ReceivedFecPacket : public ForwardErrorCorrection::SortablePacket { | |
227 public: | |
228 ProtectedPacketList protected_pkt_list; | |
229 uint32_t ssrc; // SSRC of the current frame. | |
230 rtc::scoped_refptr<ForwardErrorCorrection::Packet> pkt; | |
231 }; | |
232 | |
233 using ReceivedFecPacketList = std::list<std::unique_ptr<ReceivedFecPacket>>; | |
213 | 234 |
214 // Analyzes |media_packets| for holes in the sequence and inserts zero columns | 235 // Analyzes |media_packets| for holes in the sequence and inserts zero columns |
215 // into the |packet_mask| where those holes are found. Zero columns means that | 236 // into the |packet_mask| where those holes are found. Zero columns means that |
216 // those packets will have no protection. | 237 // those packets will have no protection. |
217 // Returns the number of bits used for one row of the new packet mask. | 238 // Returns the number of bits used for one row of the new packet mask. |
218 // Requires that |packet_mask| has at least 6 * |num_fec_packets| bytes | 239 // Requires that |packet_mask| has at least 6 * |num_fec_packets| bytes |
219 // allocated. | 240 // allocated. |
220 int InsertZerosInBitMasks(const PacketList& media_packets, | 241 int InsertZerosInBitMasks(const PacketList& media_packets, |
221 uint8_t* packet_mask, int num_mask_bytes, | 242 uint8_t* packet_mask, int num_mask_bytes, |
222 int num_fec_packets); | 243 int num_fec_packets); |
(...skipping 12 matching lines...) Expand all Loading... | |
235 // represent the number of bytes used per row for each mask. |num_fec_packets| | 256 // represent the number of bytes used per row for each mask. |num_fec_packets| |
236 // represent the number of rows of the masks. | 257 // represent the number of rows of the masks. |
237 // The copied bit is shifted out from |old_mask| and is shifted one step to | 258 // The copied bit is shifted out from |old_mask| and is shifted one step to |
238 // the left in |new_mask|. |new_mask| will contain "xxxx xxn0" after this | 259 // the left in |new_mask|. |new_mask| will contain "xxxx xxn0" after this |
239 // operation, where x are previously inserted bits and n is the new bit. | 260 // operation, where x are previously inserted bits and n is the new bit. |
240 static void CopyColumn(uint8_t* new_mask, int new_mask_bytes, | 261 static void CopyColumn(uint8_t* new_mask, int new_mask_bytes, |
241 uint8_t* old_mask, int old_mask_bytes, | 262 uint8_t* old_mask, int old_mask_bytes, |
242 int num_fec_packets, int new_bit_index, | 263 int num_fec_packets, int new_bit_index, |
243 int old_bit_index); | 264 int old_bit_index); |
244 | 265 |
245 void GenerateFecUlpHeaders(const PacketList& media_packet_list, | 266 void GenerateFecUlpHeaders(const PacketList& media_packets, |
246 uint8_t* packet_mask, int num_fec_packets, | 267 uint8_t* packet_mask, int num_fec_packets, |
247 bool l_bit); | 268 bool l_bit); |
248 | 269 |
249 void GenerateFecBitStrings(const PacketList& media_packet_list, | 270 void GenerateFecBitStrings(const PacketList& media_packets, |
250 uint8_t* packet_mask, int num_fec_packets, | 271 uint8_t* packet_mask, int num_fec_packets, |
251 bool l_bit); | 272 bool l_bit); |
252 | 273 |
253 // Insert received packets into FEC or recovered list. | 274 // Insert received packets into FEC or recovered list. |
254 void InsertPackets(ReceivedPacketList* received_packet_list, | 275 void InsertPackets(ReceivedPacketList* received_packets, |
255 RecoveredPacketList* recovered_packet_list); | 276 RecoveredPacketList* recovered_packets); |
256 | 277 |
257 // Insert media packet into recovered packet list. We delete duplicates. | 278 // Insert media packet into recovered packet list. We delete duplicates. |
258 void InsertMediaPacket(ReceivedPacket* rx_packet, | 279 void InsertMediaPacket(ReceivedPacket* rx_packet, |
259 RecoveredPacketList* recovered_packet_list); | 280 RecoveredPacketList* recovered_packets); |
260 | 281 |
261 // Assigns pointers to the recovered packet from all FEC packets which cover | 282 // Assigns pointers to the recovered packet from all FEC packets which cover |
262 // it. | 283 // it. |
263 // Note: This reduces the complexity when we want to try to recover a packet | 284 // Note: This reduces the complexity when we want to try to recover a packet |
264 // since we don't have to find the intersection between recovered packets and | 285 // since we don't have to find the intersection between recovered packets and |
265 // packets covered by the FEC packet. | 286 // packets covered by the FEC packet. |
266 void UpdateCoveringFecPackets(RecoveredPacket* packet); | 287 void UpdateCoveringFecPackets(RecoveredPacket* packet); |
267 | 288 |
268 // Insert packet into FEC list. We delete duplicates. | 289 // Insert packet into FEC list. We delete duplicates. |
269 void InsertFecPacket(ReceivedPacket* rx_packet, | 290 void InsertFecPacket(ReceivedPacket* rx_packet, |
270 const RecoveredPacketList* recovered_packet_list); | 291 const RecoveredPacketList* recovered_packets); |
271 | 292 |
272 // Assigns pointers to already recovered packets covered by this FEC packet. | 293 // Assigns pointers to already recovered packets covered by this FEC packet. |
273 static void AssignRecoveredPackets( | 294 static void AssignRecoveredPackets( |
274 FecPacket* fec_packet, const RecoveredPacketList* recovered_packets); | 295 ReceivedFecPacket* fec_packet, |
296 const RecoveredPacketList* recovered_packets); | |
275 | 297 |
276 // Insert into recovered list in correct position. | 298 // Insert into recovered list in correct position. |
277 void InsertRecoveredPacket(RecoveredPacket* rec_packet_to_insert, | 299 void InsertRecoveredPacket(RecoveredPacket* rec_packet_to_insert, |
278 RecoveredPacketList* recovered_packet_list); | 300 RecoveredPacketList* recovered_packets); |
279 | 301 |
280 // Attempt to recover missing packets. | 302 // Attempt to recover missing packets. |
281 void AttemptRecover(RecoveredPacketList* recovered_packet_list); | 303 void AttemptRecover(RecoveredPacketList* recovered_packets); |
282 | 304 |
283 // Initializes the packet recovery using the FEC packet. | 305 // Initializes the packet recovery using the FEC packet. |
284 static bool StartPacketRecovery(const FecPacket* fec_packet, | 306 static bool StartPacketRecovery(const ReceivedFecPacket* fec_packet, |
285 RecoveredPacket* recovered); | 307 RecoveredPacket* recovered); |
286 | 308 |
287 // Performs XOR between |src_packet| and |dst_packet| and stores the result | 309 // Performs XOR between |src_packet| and |dst_packet| and stores the result |
288 // in |dst_packet|. | 310 // in |dst_packet|. |
289 static void XorPackets(const Packet* src_packet, RecoveredPacket* dst_packet); | 311 static void XorPackets(const Packet* src_packet, RecoveredPacket* dst_packet); |
290 | 312 |
291 // Finish up the recovery of a packet. | 313 // Finish up the recovery of a packet. |
292 static bool FinishPacketRecovery(RecoveredPacket* recovered); | 314 static bool FinishPacketRecovery(RecoveredPacket* recovered); |
293 | 315 |
294 // Recover a missing packet. | 316 // Recover a missing packet. |
295 bool RecoverPacket(const FecPacket* fec_packet, | 317 bool RecoverPacket(const ReceivedFecPacket* fec_packet, |
296 RecoveredPacket* rec_packet_to_insert); | 318 RecoveredPacket* rec_packet_to_insert); |
297 | 319 |
298 // Get the number of missing media packets which are covered by this | 320 // Get the number of missing media packets which are covered by this |
299 // FEC packet. An FEC packet can recover at most one packet, and if zero | 321 // FEC packet. An FEC packet can recover at most one packet, and if zero |
300 // packets are missing the FEC packet can be discarded. | 322 // packets are missing the FEC packet can be discarded. |
301 // This function returns 2 when two or more packets are missing. | 323 // This function returns 2 when two or more packets are missing. |
302 static int NumCoveredPacketsMissing(const FecPacket* fec_packet); | 324 static int NumCoveredPacketsMissing(const ReceivedFecPacket* fec_packet); |
303 | 325 |
304 static void DiscardFecPacket(FecPacket* fec_packet); | 326 static void DiscardOldRecoveredPackets( |
305 static void DiscardOldPackets(RecoveredPacketList* recovered_packet_list); | 327 RecoveredPacketList* recovered_packets); |
306 static uint16_t ParseSequenceNumber(uint8_t* packet); | 328 static uint16_t ParseSequenceNumber(uint8_t* packet); |
307 | 329 |
308 std::vector<Packet> generated_fec_packets_; | 330 std::vector<Packet> generated_fec_packets_; |
309 FecPacketList fec_packet_list_; | 331 ReceivedFecPacketList received_fec_packets_; |
310 | 332 |
311 // Arrays used to avoid dynamically allocating memory when generating | 333 // Arrays used to avoid dynamically allocating memory when generating |
312 // the packet masks in the ULPFEC headers. | 334 // the packet masks in the ULPFEC headers. |
313 // (There are never more than |kMaxMediaPackets| FEC packets generated.) | 335 // (There are never more than |kMaxMediaPackets| FEC packets generated.) |
314 uint8_t packet_mask_[kMaxMediaPackets * kMaskSizeLBitSet]; | 336 uint8_t packet_mask_[kMaxMediaPackets * kMaskSizeLBitSet]; |
315 uint8_t tmp_packet_mask_[kMaxMediaPackets * kMaskSizeLBitSet]; | 337 uint8_t tmp_packet_mask_[kMaxMediaPackets * kMaskSizeLBitSet]; |
316 }; | 338 }; |
317 } // namespace webrtc | 339 } // namespace webrtc |
318 #endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_FORWARD_ERROR_CORRECTION_H_ | 340 #endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_FORWARD_ERROR_CORRECTION_H_ |
OLD | NEW |