Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(85)

Side by Side Diff: webrtc/modules/rtp_rtcp/source/forward_error_correction.cc

Issue 2260803002: Generalize FEC header formatting. (pt. 4) (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Feedback response (with accidental rebase). Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 #include "webrtc/modules/rtp_rtcp/source/forward_error_correction.h" 11 #include "webrtc/modules/rtp_rtcp/source/forward_error_correction.h"
12 12
13 #include <string.h> 13 #include <string.h>
14 14
15 #include <algorithm> 15 #include <algorithm>
16 #include <iterator> 16 #include <iterator>
17 #include <utility> 17 #include <utility>
18 18
19 #include "webrtc/base/checks.h" 19 #include "webrtc/base/checks.h"
20 #include "webrtc/base/logging.h" 20 #include "webrtc/base/logging.h"
21 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" 21 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
22 #include "webrtc/modules/rtp_rtcp/source/byte_io.h" 22 #include "webrtc/modules/rtp_rtcp/source/byte_io.h"
23 #include "webrtc/modules/rtp_rtcp/source/forward_error_correction_internal.h" 23 #include "webrtc/modules/rtp_rtcp/source/forward_error_correction_internal.h"
24 #include "webrtc/modules/rtp_rtcp/source/ulpfec_header_reader_writer.h"
24 25
25 namespace webrtc { 26 namespace webrtc {
26 27
27 // FEC header size in bytes. 28 namespace {
28 constexpr size_t kFecHeaderSize = 10;
29
30 // ULP header size in bytes (L bit is set).
31 constexpr size_t kUlpHeaderSizeLBitSet = (2 + kMaskSizeLBitSet);
32
33 // ULP header size in bytes (L bit is cleared).
34 constexpr size_t kUlpHeaderSizeLBitClear = (2 + kMaskSizeLBitClear);
35
36 // Transport header size in bytes. Assume UDP/IPv4 as a reasonable minimum. 29 // Transport header size in bytes. Assume UDP/IPv4 as a reasonable minimum.
37 constexpr size_t kTransportOverhead = 28; 30 constexpr size_t kTransportOverhead = 28;
31 } // namespace
38 32
39 // Maximum number of media packets that can be protected. 33 ForwardErrorCorrection::Packet::Packet() : length(0), data(), ref_count_(0) {}
40 constexpr size_t ForwardErrorCorrection::kMaxMediaPackets; 34 ForwardErrorCorrection::Packet::~Packet() = default;
41
42 // Maximum number of FEC packets stored internally.
43 constexpr size_t kMaxFecPackets = ForwardErrorCorrection::kMaxMediaPackets;
44 35
45 int32_t ForwardErrorCorrection::Packet::AddRef() { 36 int32_t ForwardErrorCorrection::Packet::AddRef() {
46 return ++ref_count_; 37 return ++ref_count_;
47 } 38 }
48 39
49 int32_t ForwardErrorCorrection::Packet::Release() { 40 int32_t ForwardErrorCorrection::Packet::Release() {
50 int32_t ref_count; 41 int32_t ref_count;
51 ref_count = --ref_count_; 42 ref_count = --ref_count_;
52 if (ref_count == 0) 43 if (ref_count == 0)
53 delete this; 44 delete this;
54 return ref_count; 45 return ref_count;
55 } 46 }
56 47
57 // This comparator is used to compare std::unique_ptr's pointing to 48 // This comparator is used to compare std::unique_ptr's pointing to
58 // subclasses of SortablePackets. It needs to be parametric since 49 // subclasses of SortablePackets. It needs to be parametric since
59 // the std::unique_ptr's are not covariant w.r.t. the types that 50 // the std::unique_ptr's are not covariant w.r.t. the types that
60 // they are pointing to. 51 // they are pointing to.
61 template <typename S, typename T> 52 template <typename S, typename T>
62 bool ForwardErrorCorrection::SortablePacket::LessThan::operator() ( 53 bool ForwardErrorCorrection::SortablePacket::LessThan::operator() (
63 const S& first, 54 const S& first,
64 const T& second) { 55 const T& second) {
65 return IsNewerSequenceNumber(second->seq_num, first->seq_num); 56 return IsNewerSequenceNumber(second->seq_num, first->seq_num);
66 } 57 }
67 58
68 ForwardErrorCorrection::ReceivedPacket::ReceivedPacket() {} 59 ForwardErrorCorrection::ReceivedPacket::ReceivedPacket() = default;
69 ForwardErrorCorrection::ReceivedPacket::~ReceivedPacket() {} 60 ForwardErrorCorrection::ReceivedPacket::~ReceivedPacket() = default;
70 61
71 ForwardErrorCorrection::RecoveredPacket::RecoveredPacket() {} 62 ForwardErrorCorrection::RecoveredPacket::RecoveredPacket() = default;
72 ForwardErrorCorrection::RecoveredPacket::~RecoveredPacket() {} 63 ForwardErrorCorrection::RecoveredPacket::~RecoveredPacket() = default;
73 64
74 ForwardErrorCorrection::ForwardErrorCorrection() 65 ForwardErrorCorrection::ProtectedPacket::ProtectedPacket() = default;
75 : generated_fec_packets_(kMaxMediaPackets), received_fec_packets_(), 66 ForwardErrorCorrection::ProtectedPacket::~ProtectedPacket() = default;
76 packet_mask_(), tmp_packet_mask_() {}
77 ForwardErrorCorrection::~ForwardErrorCorrection() {}
78 67
79 // Input packet 68 ForwardErrorCorrection::ReceivedFecPacket::ReceivedFecPacket() = default;
80 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 69 ForwardErrorCorrection::ReceivedFecPacket::~ReceivedFecPacket() = default;
81 // | RTP Header (12 octets) |
82 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
83 // | RTP Payload |
84 // | |
85 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
86 70
87 // Output packet 71 ForwardErrorCorrection::ForwardErrorCorrection(
88 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 72 std::unique_ptr<FecHeaderReader> fec_header_reader,
89 // | FEC Header (10 octets) | 73 std::unique_ptr<FecHeaderWriter> fec_header_writer)
90 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 74 : fec_header_reader_(std::move(fec_header_reader)),
91 // | FEC Level 0 Header | 75 fec_header_writer_(std::move(fec_header_writer)),
92 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 76 generated_fec_packets_(fec_header_writer_->MaxFecPackets()),
93 // | FEC Level 0 Payload | 77 packet_mask_size_(0) {}
94 // | | 78
95 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 79 std::unique_ptr<ForwardErrorCorrection> ForwardErrorCorrection::CreateUlpfec() {
96 // 80 std::unique_ptr<FecHeaderReader> fec_header_reader(new UlpfecHeaderReader());
81 std::unique_ptr<FecHeaderWriter> fec_header_writer(new UlpfecHeaderWriter());
82 return std::unique_ptr<ForwardErrorCorrection>(new ForwardErrorCorrection(
83 std::move(fec_header_reader), std::move(fec_header_writer)));
84 }
85
97 int ForwardErrorCorrection::EncodeFec(const PacketList& media_packets, 86 int ForwardErrorCorrection::EncodeFec(const PacketList& media_packets,
98 uint8_t protection_factor, 87 uint8_t protection_factor,
99 int num_important_packets, 88 int num_important_packets,
100 bool use_unequal_protection, 89 bool use_unequal_protection,
101 FecMaskType fec_mask_type, 90 FecMaskType fec_mask_type,
102 std::list<Packet*>* fec_packets) { 91 std::list<Packet*>* fec_packets) {
103 const size_t num_media_packets = media_packets.size(); 92 const size_t num_media_packets = media_packets.size();
104 93
105 // Sanity check arguments. 94 // Sanity check arguments.
106 RTC_DCHECK_GT(num_media_packets, 0u); 95 RTC_DCHECK_GT(num_media_packets, 0u);
107 RTC_DCHECK_GE(num_important_packets, 0); 96 RTC_DCHECK_GE(num_important_packets, 0);
108 RTC_DCHECK_LE(static_cast<size_t>(num_important_packets), num_media_packets); 97 RTC_DCHECK_LE(static_cast<size_t>(num_important_packets), num_media_packets);
109 RTC_DCHECK(fec_packets->empty()); 98 RTC_DCHECK(fec_packets->empty());
110 99 const size_t max_media_packets = fec_header_writer_->MaxMediaPackets();
111 if (num_media_packets > kMaxMediaPackets) { 100 if (num_media_packets > max_media_packets) {
112 LOG(LS_WARNING) << "Can't protect " << num_media_packets 101 LOG(LS_WARNING) << "Can't protect " << num_media_packets
113 << " media packets per frame. Max is " << kMaxMediaPackets 102 << " media packets per frame. Max is " << max_media_packets
114 << "."; 103 << ".";
115 return -1; 104 return -1;
116 } 105 }
117 106
118 bool l_bit = (num_media_packets > 8 * kMaskSizeLBitClear);
119 int num_mask_bytes = l_bit ? kMaskSizeLBitSet : kMaskSizeLBitClear;
120
121 // Error check the media packets. 107 // Error check the media packets.
122 for (const auto& media_packet : media_packets) { 108 for (const auto& media_packet : media_packets) {
123 RTC_DCHECK(media_packet); 109 RTC_DCHECK(media_packet);
124 if (media_packet->length < kRtpHeaderSize) { 110 if (media_packet->length < kRtpHeaderSize) {
125 LOG(LS_WARNING) << "Media packet " << media_packet->length << " bytes " 111 LOG(LS_WARNING) << "Media packet " << media_packet->length << " bytes "
126 << "is smaller than RTP header."; 112 << "is smaller than RTP header.";
127 return -1; 113 return -1;
128 } 114 }
129 // Ensure the FEC packets will fit in a typical MTU. 115 // Ensure the FEC packets will fit in a typical MTU.
130 if (media_packet->length + MaxPacketOverhead() + kTransportOverhead > 116 if (media_packet->length + MaxPacketOverhead() + kTransportOverhead >
131 IP_PACKET_SIZE) { 117 IP_PACKET_SIZE) {
132 LOG(LS_WARNING) << "Media packet " << media_packet->length << " bytes " 118 LOG(LS_WARNING) << "Media packet " << media_packet->length << " bytes "
133 << "with overhead is larger than " << IP_PACKET_SIZE 119 << "with overhead is larger than " << IP_PACKET_SIZE
134 << " bytes."; 120 << " bytes.";
135 } 121 }
136 } 122 }
137 123
124 // Prepare generated FEC packets.
138 int num_fec_packets = NumFecPackets(num_media_packets, protection_factor); 125 int num_fec_packets = NumFecPackets(num_media_packets, protection_factor);
139 if (num_fec_packets == 0) { 126 if (num_fec_packets == 0) {
140 return 0; 127 return 0;
141 } 128 }
142
143 // Prepare generated FEC packets by setting them to 0.
144 for (int i = 0; i < num_fec_packets; ++i) { 129 for (int i = 0; i < num_fec_packets; ++i) {
145 memset(generated_fec_packets_[i].data, 0, IP_PACKET_SIZE); 130 memset(generated_fec_packets_[i].data, 0, IP_PACKET_SIZE);
146 // Use this as a marker for untouched packets. 131 // Use this as a marker for untouched packets.
147 generated_fec_packets_[i].length = 0; 132 generated_fec_packets_[i].length = 0;
148 fec_packets->push_back(&generated_fec_packets_[i]); 133 fec_packets->push_back(&generated_fec_packets_[i]);
149 } 134 }
150 135
151 const internal::PacketMaskTable mask_table(fec_mask_type, num_media_packets); 136 const internal::PacketMaskTable mask_table(fec_mask_type, num_media_packets);
152 137 packet_mask_size_ = internal::PacketMaskSize(num_media_packets);
153 // -- Generate packet masks -- 138 memset(packet_masks_, 0, num_fec_packets * packet_mask_size_);
154 memset(packet_mask_, 0, num_fec_packets * num_mask_bytes);
155 internal::GeneratePacketMasks(num_media_packets, num_fec_packets, 139 internal::GeneratePacketMasks(num_media_packets, num_fec_packets,
156 num_important_packets, use_unequal_protection, 140 num_important_packets, use_unequal_protection,
157 mask_table, packet_mask_); 141 mask_table, packet_masks_);
158 142
159 int num_mask_bits = InsertZerosInBitMasks( 143 // Adapt packet masks to missing media packets.
160 media_packets, packet_mask_, num_mask_bytes, num_fec_packets); 144 int num_mask_bits = InsertZerosInPacketMasks(media_packets, num_fec_packets);
161
162 if (num_mask_bits < 0) { 145 if (num_mask_bits < 0) {
163 return -1; 146 return -1;
164 } 147 }
165 l_bit = (static_cast<size_t>(num_mask_bits) > 8 * kMaskSizeLBitClear); 148 packet_mask_size_ = internal::PacketMaskSize(num_mask_bits);
166 if (l_bit) {
167 num_mask_bytes = kMaskSizeLBitSet;
168 }
169 149
170 GenerateFecBitStrings(media_packets, packet_mask_, num_fec_packets, l_bit); 150 // Write FEC packets to |generated_fec_packets_|.
171 GenerateFecUlpHeaders(media_packets, packet_mask_, num_fec_packets, l_bit); 151 GenerateFecPayloads(media_packets, num_fec_packets);
152 FinalizeFecHeaders(media_packets, num_fec_packets);
172 153
173 return 0; 154 return 0;
174 } 155 }
175 156
176 int ForwardErrorCorrection::NumFecPackets(int num_media_packets, 157 int ForwardErrorCorrection::NumFecPackets(int num_media_packets,
177 int protection_factor) { 158 int protection_factor) {
178 // Result in Q0 with an unsigned round. 159 // Result in Q0 with an unsigned round.
179 int num_fec_packets = (num_media_packets * protection_factor + (1 << 7)) >> 8; 160 int num_fec_packets = (num_media_packets * protection_factor + (1 << 7)) >> 8;
180 // Generate at least one FEC packet if we need protection. 161 // Generate at least one FEC packet if we need protection.
181 if (protection_factor > 0 && num_fec_packets == 0) { 162 if (protection_factor > 0 && num_fec_packets == 0) {
182 num_fec_packets = 1; 163 num_fec_packets = 1;
183 } 164 }
184 RTC_DCHECK_LE(num_fec_packets, num_media_packets); 165 RTC_DCHECK_LE(num_fec_packets, num_media_packets);
185 return num_fec_packets; 166 return num_fec_packets;
186 } 167 }
187 168
188 void ForwardErrorCorrection::GenerateFecBitStrings( 169 void ForwardErrorCorrection::GenerateFecPayloads(
189 const PacketList& media_packets, 170 const PacketList& media_packets,
190 uint8_t* packet_mask, 171 size_t num_fec_packets) {
191 int num_fec_packets,
192 bool l_bit) {
193 RTC_DCHECK(!media_packets.empty()); 172 RTC_DCHECK(!media_packets.empty());
194 uint8_t media_payload_length[2]; 173 for (size_t i = 0; i < num_fec_packets; ++i) {
195 const int num_mask_bytes = l_bit ? kMaskSizeLBitSet : kMaskSizeLBitClear; 174 Packet* const fec_packet = &generated_fec_packets_[i];
196 const uint16_t ulp_header_size = 175 uint32_t pkt_mask_idx = i * packet_mask_size_;
danilchap 2016/08/29 12:26:02 since you touch almost all lines in this function,
brandtr 2016/08/30 07:12:40 Done.
197 l_bit ? kUlpHeaderSizeLBitSet : kUlpHeaderSizeLBitClear; 176 const size_t min_packet_mask_size = fec_header_writer_->MinPacketMaskSize(
198 const uint16_t fec_rtp_offset = 177 &packet_masks_[pkt_mask_idx], packet_mask_size_);
199 kFecHeaderSize + ulp_header_size - kRtpHeaderSize; 178 const size_t fec_header_size =
179 fec_header_writer_->FecHeaderSize(min_packet_mask_size);
200 180
201 for (int i = 0; i < num_fec_packets; ++i) { 181 uint32_t media_pkt_idx = 0;
danilchap 2016/08/29 12:26:02 size_t
brandtr 2016/08/30 07:12:40 Done.
202 Packet* const fec_packet = &generated_fec_packets_[i];
203 auto media_packets_it = media_packets.cbegin(); 182 auto media_packets_it = media_packets.cbegin();
204 uint32_t pkt_mask_idx = i * num_mask_bytes;
205 uint32_t media_pkt_idx = 0;
206 uint16_t fec_packet_length = 0;
207 uint16_t prev_seq_num = ParseSequenceNumber((*media_packets_it)->data); 183 uint16_t prev_seq_num = ParseSequenceNumber((*media_packets_it)->data);
208 while (media_packets_it != media_packets.end()) { 184 while (media_packets_it != media_packets.end()) {
209 // Each FEC packet has a multiple byte mask. Determine if this media 185 Packet* const media_packet = media_packets_it->get();
210 // packet should be included in FEC packet i. 186 // Should |media_packet| be protected by |fec_packet|?
211 if (packet_mask[pkt_mask_idx] & (1 << (7 - media_pkt_idx))) { 187 if (packet_masks_[pkt_mask_idx] & (1 << (7 - media_pkt_idx))) {
212 Packet* media_packet = media_packets_it->get(); 188 size_t media_payload_length = media_packet->length - kRtpHeaderSize;
189 uint8_t media_payload_length_network_order[2];
190 ByteWriter<uint16_t>::WriteBigEndian(media_payload_length_network_order,
danilchap 2016/08/29 12:26:02 this now used in if (first_protected_packet) only.
brandtr 2016/08/30 07:12:40 Done.
191 media_payload_length);
213 192
214 // Assign network-ordered media payload length. 193 bool first_protected_packet = (fec_packet->length == 0);
215 ByteWriter<uint16_t>::WriteBigEndian( 194 size_t fec_packet_length = fec_header_size + media_payload_length;
216 media_payload_length, media_packet->length - kRtpHeaderSize); 195 if (fec_packet_length > fec_packet->length) {
217 196 // Recall that XORing with zero (which the FEC packets are prefilled
218 fec_packet_length = media_packet->length + fec_rtp_offset; 197 // with) is the identity operator, thus all prior XORs are
219 // On the first protected packet, we don't need to XOR. 198 // still correct even though we expand the packet length here.
220 if (fec_packet->length == 0) { 199 fec_packet->length = fec_packet_length;
221 // Copy the first 2 bytes of the RTP header. Note that the E and L 200 }
222 // bits are overwritten in GenerateFecUlpHeaders. 201 if (first_protected_packet) {
202 // Write P, X, CC, M, and PT recovery fields.
203 // Note that bits 0, 1, and 16 are overwritten in FinalizeFecHeaders.
223 memcpy(&fec_packet->data[0], &media_packet->data[0], 2); 204 memcpy(&fec_packet->data[0], &media_packet->data[0], 2);
224 // Copy the 5th to 8th bytes of the RTP header (timestamp). 205 // Write length recovery field. (This is a temporary location for
206 // ULPFEC.)
207 memcpy(&fec_packet->data[2], media_payload_length_network_order, 2);
208 // Write timestamp recovery field.
225 memcpy(&fec_packet->data[4], &media_packet->data[4], 4); 209 memcpy(&fec_packet->data[4], &media_packet->data[4], 4);
226 // Copy network-ordered payload size. 210 // Write payload.
227 memcpy(&fec_packet->data[8], media_payload_length, 2); 211 memcpy(&fec_packet->data[fec_header_size],
228 212 &media_packet->data[kRtpHeaderSize], media_payload_length);
229 // Copy RTP payload, leaving room for the ULP header.
230 memcpy(&fec_packet->data[kFecHeaderSize + ulp_header_size],
231 &media_packet->data[kRtpHeaderSize],
232 media_packet->length - kRtpHeaderSize);
233 } else { 213 } else {
234 // XOR with the first 2 bytes of the RTP header. 214 XorPackets(*media_packet, kRtpHeaderSize,
235 fec_packet->data[0] ^= media_packet->data[0]; 215 fec_packet_length - fec_header_size, fec_header_size,
danilchap 2016/08/29 12:26:02 maybe media_payload_length instead of fec_packet_l
brandtr 2016/08/30 07:12:40 Done.
236 fec_packet->data[1] ^= media_packet->data[1]; 216 fec_packet);
237
238 // XOR with the 5th to 8th bytes of the RTP header.
239 for (uint32_t j = 4; j < 8; ++j) {
240 fec_packet->data[j] ^= media_packet->data[j];
241 }
242
243 // XOR with the network-ordered payload size.
244 fec_packet->data[8] ^= media_payload_length[0];
245 fec_packet->data[9] ^= media_payload_length[1];
246
247 // XOR with RTP payload, leaving room for the ULP header.
248 for (int32_t j = kFecHeaderSize + ulp_header_size;
249 j < fec_packet_length; j++) {
250 fec_packet->data[j] ^= media_packet->data[j - fec_rtp_offset];
251 }
252 }
253 if (fec_packet_length > fec_packet->length) {
254 fec_packet->length = fec_packet_length;
255 } 217 }
256 } 218 }
257 media_packets_it++; 219 media_packets_it++;
258 if (media_packets_it != media_packets.end()) { 220 if (media_packets_it != media_packets.end()) {
259 uint16_t seq_num = ParseSequenceNumber((*media_packets_it)->data); 221 uint16_t seq_num = ParseSequenceNumber((*media_packets_it)->data);
260 media_pkt_idx += static_cast<uint16_t>(seq_num - prev_seq_num); 222 media_pkt_idx += static_cast<uint16_t>(seq_num - prev_seq_num);
261 prev_seq_num = seq_num; 223 prev_seq_num = seq_num;
262 } 224 }
263 pkt_mask_idx += media_pkt_idx / 8; 225 pkt_mask_idx += media_pkt_idx / 8;
264 media_pkt_idx %= 8; 226 media_pkt_idx %= 8;
265 } 227 }
266 RTC_DCHECK_GT(fec_packet->length, 0u) 228 RTC_DCHECK_GT(fec_packet->length, 0u)
267 << "Packet mask is wrong or poorly designed."; 229 << "Packet mask is wrong or poorly designed.";
268 } 230 }
269 } 231 }
270 232
271 int ForwardErrorCorrection::InsertZerosInBitMasks( 233 int ForwardErrorCorrection::InsertZerosInPacketMasks(
272 const PacketList& media_packets, 234 const PacketList& media_packets,
273 uint8_t* packet_mask, 235 size_t num_fec_packets) {
274 int num_mask_bytes, 236 size_t num_media_packets = media_packets.size();
275 int num_fec_packets) { 237 if (num_media_packets <= 1) {
276 if (media_packets.size() <= 1) { 238 return num_media_packets;
277 return media_packets.size();
278 } 239 }
279 int last_seq_num = ParseSequenceNumber(media_packets.back()->data); 240 uint16_t last_seq_num = ParseSequenceNumber(media_packets.back()->data);
280 int first_seq_num = ParseSequenceNumber(media_packets.front()->data); 241 uint16_t first_seq_num = ParseSequenceNumber(media_packets.front()->data);
281 int total_missing_seq_nums = 242 uint16_t total_missing_seq_nums =
danilchap 2016/08/29 12:26:02 this variable represent number of, not a sequence
brandtr 2016/08/30 07:12:40 Done.
282 static_cast<uint16_t>(last_seq_num - first_seq_num) - 243 static_cast<uint16_t>(last_seq_num - first_seq_num) - num_media_packets +
danilchap 2016/08/29 12:26:02 this static_cast shouldn't be needed now: uint16_t
brandtr 2016/08/30 07:12:40 Seems to still be needed for correct wrapping, aft
danilchap 2016/08/30 12:29:01 Yep, I was wrong, better leave this static_cast. N
brandtr 2016/08/30 14:14:24 I guess it has something to do with promotion logi
283 media_packets.size() + 1; 244 1;
284 if (total_missing_seq_nums == 0) { 245 if (total_missing_seq_nums == 0) {
285 // All sequence numbers are covered by the packet mask. No zero insertion 246 // All sequence numbers are covered by the packet mask.
286 // required. 247 // No zero insertion required.
287 return media_packets.size(); 248 return num_media_packets;
288 } 249 }
289 // We can only protect 8 * kMaskSizeLBitSet packets. 250 if (total_missing_seq_nums + num_media_packets > kUlpfecMaxMediaPackets) {
danilchap 2016/08/29 12:26:02 probably fec_header_writer_->MaxMediaPackets() ins
brandtr 2016/08/30 07:12:40 Done.
290 if (total_missing_seq_nums + media_packets.size() > 8 * kMaskSizeLBitSet)
291 return -1; 251 return -1;
252 }
292 // Allocate the new mask. 253 // Allocate the new mask.
293 int new_mask_bytes = kMaskSizeLBitClear; 254 size_t tmp_packet_mask_size =
294 if (media_packets.size() + 255 internal::PacketMaskSize(total_missing_seq_nums + num_media_packets);
295 total_missing_seq_nums > 8 * kMaskSizeLBitClear) { 256 memset(tmp_packet_masks_, 0, num_fec_packets * tmp_packet_mask_size);
296 new_mask_bytes = kMaskSizeLBitSet;
297 }
298 memset(tmp_packet_mask_, 0, num_fec_packets * kMaskSizeLBitSet);
299 257
300 auto media_packets_it = media_packets.cbegin(); 258 auto media_packets_it = media_packets.cbegin();
301 uint16_t prev_seq_num = first_seq_num; 259 uint16_t prev_seq_num = first_seq_num;
302 ++media_packets_it; 260 ++media_packets_it;
303 261
304 // Insert the first column. 262 // Insert the first column.
305 internal::CopyColumn(tmp_packet_mask_, new_mask_bytes, packet_mask_, 263 internal::CopyColumn(tmp_packet_masks_, tmp_packet_mask_size, packet_masks_,
306 num_mask_bytes, num_fec_packets, 0, 0); 264 packet_mask_size_, num_fec_packets, 0, 0);
307 size_t new_bit_index = 1; 265 size_t new_bit_index = 1;
308 size_t old_bit_index = 1; 266 size_t old_bit_index = 1;
309 // Insert zeros in the bit mask for every hole in the sequence. 267 // Insert zeros in the bit mask for every hole in the sequence.
310 while (media_packets_it != media_packets.end()) { 268 while (media_packets_it != media_packets.end()) {
311 if (new_bit_index == 8 * kMaskSizeLBitSet) { 269 if (new_bit_index == kUlpfecMaxMediaPackets) {
danilchap 2016/08/29 12:26:02 ditto
brandtr 2016/08/30 07:12:40 Done.
312 // We can only cover up to 48 packets. 270 // We can only cover up to 48 packets.
313 break; 271 break;
314 } 272 }
315 uint16_t seq_num = ParseSequenceNumber((*media_packets_it)->data); 273 uint16_t seq_num = ParseSequenceNumber((*media_packets_it)->data);
316 const int num_zeros_to_insert = 274 const int num_zeros_to_insert =
317 static_cast<uint16_t>(seq_num - prev_seq_num - 1); 275 static_cast<uint16_t>(seq_num - prev_seq_num - 1);
318 if (num_zeros_to_insert > 0) { 276 if (num_zeros_to_insert > 0) {
319 internal::InsertZeroColumns(num_zeros_to_insert, tmp_packet_mask_, 277 internal::InsertZeroColumns(num_zeros_to_insert, tmp_packet_masks_,
320 new_mask_bytes, num_fec_packets, 278 tmp_packet_mask_size, num_fec_packets,
321 new_bit_index); 279 new_bit_index);
322 } 280 }
323 new_bit_index += num_zeros_to_insert; 281 new_bit_index += num_zeros_to_insert;
324 internal::CopyColumn(tmp_packet_mask_, new_mask_bytes, packet_mask_, 282 internal::CopyColumn(tmp_packet_masks_, tmp_packet_mask_size, packet_masks_,
325 num_mask_bytes, num_fec_packets, new_bit_index, 283 packet_mask_size_, num_fec_packets, new_bit_index,
326 old_bit_index); 284 old_bit_index);
327 ++new_bit_index; 285 ++new_bit_index;
328 ++old_bit_index; 286 ++old_bit_index;
329 prev_seq_num = seq_num; 287 prev_seq_num = seq_num;
330 ++media_packets_it; 288 ++media_packets_it;
331 } 289 }
332 if (new_bit_index % 8 != 0) { 290 if (new_bit_index % 8 != 0) {
333 // We didn't fill the last byte. Shift bits to correct position. 291 // We didn't fill the last byte. Shift bits to correct position.
334 for (uint16_t row = 0; row < num_fec_packets; ++row) { 292 for (uint16_t row = 0; row < num_fec_packets; ++row) {
335 int new_byte_index = row * new_mask_bytes + new_bit_index / 8; 293 int new_byte_index = row * tmp_packet_mask_size + new_bit_index / 8;
336 tmp_packet_mask_[new_byte_index] <<= (7 - (new_bit_index % 8)); 294 tmp_packet_masks_[new_byte_index] <<= (7 - (new_bit_index % 8));
337 } 295 }
338 } 296 }
339 // Replace the old mask with the new. 297 // Replace the old mask with the new.
340 memcpy(packet_mask, tmp_packet_mask_, kMaskSizeLBitSet * num_fec_packets); 298 memcpy(packet_masks_, tmp_packet_masks_,
299 num_fec_packets * tmp_packet_mask_size);
341 return new_bit_index; 300 return new_bit_index;
342 } 301 }
343 302
344 void ForwardErrorCorrection::GenerateFecUlpHeaders( 303 void ForwardErrorCorrection::FinalizeFecHeaders(const PacketList& media_packets,
345 const PacketList& media_packets, 304 size_t num_fec_packets) {
346 uint8_t* packet_mask, 305 for (size_t i = 0; i < num_fec_packets; ++i) {
347 int num_fec_packets, 306 fec_header_writer_->FinalizeFecHeader(
348 bool l_bit) { 307 media_packets, &packet_masks_[i * packet_mask_size_], packet_mask_size_,
349 // -- Generate FEC and ULP headers -- 308 &generated_fec_packets_[i]);
350 //
351 // FEC Header, 10 bytes
352 // 0 1 2 3
353 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
354 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
355 // |E|L|P|X| CC |M| PT recovery | SN base |
356 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
357 // | TS recovery |
358 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
359 // | length recovery |
360 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
361 //
362 // ULP Header, 4 bytes (for L = 0)
363 // 0 1 2 3
364 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
365 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
366 // | Protection Length | mask |
367 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
368 // | mask cont. (present only when L = 1) |
369 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
370 int num_mask_bytes = l_bit ? kMaskSizeLBitSet : kMaskSizeLBitClear;
371 const uint16_t ulp_header_size =
372 l_bit ? kUlpHeaderSizeLBitSet : kUlpHeaderSizeLBitClear;
373
374 RTC_DCHECK(!media_packets.empty());
375 Packet* first_media_packet = media_packets.front().get();
376 RTC_DCHECK(first_media_packet);
377 uint16_t seq_num = ParseSequenceNumber(first_media_packet->data);
378 for (int i = 0; i < num_fec_packets; ++i) {
379 Packet* const fec_packet = &generated_fec_packets_[i];
380 // -- FEC header --
381 fec_packet->data[0] &= 0x7f; // Set E to zero.
382 if (l_bit == 0) {
383 fec_packet->data[0] &= 0xbf; // Clear the L bit.
384 } else {
385 fec_packet->data[0] |= 0x40; // Set the L bit.
386 }
387 // Sequence number from first media packet used as SN base.
388 // We use the same sequence number base for every FEC packet,
389 // but that's not required in general.
390 ByteWriter<uint16_t>::WriteBigEndian(&fec_packet->data[2], seq_num);
391
392 // -- ULP header --
393 // Copy the payload size to the protection length field.
394 // (We protect the entire packet.)
395 ByteWriter<uint16_t>::WriteBigEndian(
396 &fec_packet->data[10],
397 fec_packet->length - kFecHeaderSize - ulp_header_size);
398
399 // Copy the packet mask.
400 memcpy(&fec_packet->data[12], &packet_mask[i * num_mask_bytes],
401 num_mask_bytes);
402 } 309 }
403 } 310 }
404 311
405 void ForwardErrorCorrection::ResetState( 312 void ForwardErrorCorrection::ResetState(
406 RecoveredPacketList* recovered_packets) { 313 RecoveredPacketList* recovered_packets) {
407 // Free the memory for any existing recovered packets, if the caller hasn't. 314 // Free the memory for any existing recovered packets, if the caller hasn't.
408 recovered_packets->clear(); 315 recovered_packets->clear();
409 received_fec_packets_.clear(); 316 received_fec_packets_.clear();
410 } 317 }
411 318
412 void ForwardErrorCorrection::InsertMediaPacket( 319 void ForwardErrorCorrection::InsertMediaPacket(
413 ReceivedPacket* received_packet, 320 RecoveredPacketList* recovered_packets,
414 RecoveredPacketList* recovered_packets) { 321 ReceivedPacket* received_packet) {
415
416 // Search for duplicate packets. 322 // Search for duplicate packets.
417 for (const auto& recovered_packet : *recovered_packets) { 323 for (const auto& recovered_packet : *recovered_packets) {
418 if (received_packet->seq_num == recovered_packet->seq_num) { 324 if (received_packet->seq_num == recovered_packet->seq_num) {
419 // Duplicate packet, no need to add to list. 325 // Duplicate packet, no need to add to list.
420 // Delete duplicate media packet data. 326 // Delete duplicate media packet data.
421 received_packet->pkt = nullptr; 327 received_packet->pkt = nullptr;
422 return; 328 return;
423 } 329 }
424 } 330 }
425
426 std::unique_ptr<RecoveredPacket> recovered_packet(new RecoveredPacket()); 331 std::unique_ptr<RecoveredPacket> recovered_packet(new RecoveredPacket());
427 // This "recovered packet" was not recovered using parity packets. 332 // This "recovered packet" was not recovered using parity packets.
428 recovered_packet->was_recovered = false; 333 recovered_packet->was_recovered = false;
429 // This media packet has already been passed on. 334 // This media packet has already been passed on.
430 recovered_packet->returned = true; 335 recovered_packet->returned = true;
431 recovered_packet->seq_num = received_packet->seq_num; 336 recovered_packet->seq_num = received_packet->seq_num;
432 recovered_packet->pkt = received_packet->pkt; 337 recovered_packet->pkt = received_packet->pkt;
433 recovered_packet->pkt->length = received_packet->pkt->length; 338 recovered_packet->pkt->length = received_packet->pkt->length;
434
435 RecoveredPacket* recovered_packet_ptr = recovered_packet.get();
436 // TODO(holmer): Consider replacing this with a binary search for the right 339 // TODO(holmer): Consider replacing this with a binary search for the right
437 // position, and then just insert the new packet. Would get rid of the sort. 340 // position, and then just insert the new packet. Would get rid of the sort.
341 RecoveredPacket* recovered_packet_ptr = recovered_packet.get();
438 recovered_packets->push_back(std::move(recovered_packet)); 342 recovered_packets->push_back(std::move(recovered_packet));
439 recovered_packets->sort(SortablePacket::LessThan()); 343 recovered_packets->sort(SortablePacket::LessThan());
440 UpdateCoveringFecPackets(recovered_packet_ptr); 344 UpdateCoveringFecPackets(*recovered_packet_ptr);
441 } 345 }
442 346
443 void ForwardErrorCorrection::UpdateCoveringFecPackets(RecoveredPacket* packet) { 347 void ForwardErrorCorrection::UpdateCoveringFecPackets(
348 const RecoveredPacket& packet) {
444 for (auto& fec_packet : received_fec_packets_) { 349 for (auto& fec_packet : received_fec_packets_) {
445 // Is this FEC packet protecting the media packet |packet|? 350 // Is this FEC packet protecting the media packet |packet|?
446 auto protected_it = std::lower_bound(fec_packet->protected_packets.begin(), 351 auto protected_it = std::lower_bound(fec_packet->protected_packets.begin(),
447 fec_packet->protected_packets.end(), 352 fec_packet->protected_packets.end(),
448 packet, 353 &packet, SortablePacket::LessThan());
449 SortablePacket::LessThan());
450 if (protected_it != fec_packet->protected_packets.end() && 354 if (protected_it != fec_packet->protected_packets.end() &&
451 (*protected_it)->seq_num == packet->seq_num) { 355 (*protected_it)->seq_num == packet.seq_num) {
452 // Found an FEC packet which is protecting |packet|. 356 // Found an FEC packet which is protecting |packet|.
453 (*protected_it)->pkt = packet->pkt; 357 (*protected_it)->pkt = packet.pkt;
454 } 358 }
455 } 359 }
456 } 360 }
457 361
458 void ForwardErrorCorrection::InsertFecPacket( 362 void ForwardErrorCorrection::InsertFecPacket(
459 ReceivedPacket* received_packet, 363 const RecoveredPacketList& recovered_packets,
460 const RecoveredPacketList* recovered_packets) { 364 ReceivedPacket* received_packet) {
461 // Check for duplicate. 365 // Check for duplicate.
462 for (const auto& existing_fec_packet : received_fec_packets_) { 366 for (const auto& existing_fec_packet : received_fec_packets_) {
463 if (received_packet->seq_num == existing_fec_packet->seq_num) { 367 if (received_packet->seq_num == existing_fec_packet->seq_num) {
464 // Delete duplicate FEC packet data. 368 // Delete duplicate FEC packet data.
465 received_packet->pkt = nullptr; 369 received_packet->pkt = nullptr;
466 return; 370 return;
467 } 371 }
468 } 372 }
469
470 std::unique_ptr<ReceivedFecPacket> fec_packet(new ReceivedFecPacket()); 373 std::unique_ptr<ReceivedFecPacket> fec_packet(new ReceivedFecPacket());
471 fec_packet->pkt = received_packet->pkt; 374 fec_packet->pkt = received_packet->pkt;
472 fec_packet->seq_num = received_packet->seq_num; 375 fec_packet->seq_num = received_packet->seq_num;
473 fec_packet->ssrc = received_packet->ssrc; 376 fec_packet->rtp_ssrc = received_packet->ssrc;
474 377 // Parse ULPFEC/FlexFEC header specific info.
475 const uint16_t seq_num_base = 378 bool ret = fec_header_reader_->ReadFecHeader(fec_packet.get());
476 ByteReader<uint16_t>::ReadBigEndian(&fec_packet->pkt->data[2]); 379 if (!ret) {
477 const uint16_t mask_size_bytes = (fec_packet->pkt->data[0] & 0x40) 380 LOG(LS_WARNING) << "Malformed FEC header: dropping packet.";
478 ? kMaskSizeLBitSet 381 return;
479 : kMaskSizeLBitClear; // L bit set? 382 }
480 383 // Parse packet mask from header and represent as protected packets.
481 // Parse erasure code mask from ULP header and represent as protected packets. 384 for (const auto& stream_packet_mask_info : fec_packet->packet_mask_infos) {
482 for (uint16_t byte_idx = 0; byte_idx < mask_size_bytes; ++byte_idx) { 385 uint16_t seq_num_base = stream_packet_mask_info.second.seq_num_base;
483 uint8_t packet_mask = fec_packet->pkt->data[12 + byte_idx]; 386 size_t offset = stream_packet_mask_info.second.offset;
484 for (uint16_t bit_idx = 0; bit_idx < 8; ++bit_idx) { 387 size_t size = stream_packet_mask_info.second.size;
485 if (packet_mask & (1 << (7 - bit_idx))) { 388 for (uint16_t byte_idx = 0; byte_idx < size; ++byte_idx) {
486 std::unique_ptr<ProtectedPacket> protected_packet( 389 uint8_t packet_mask = fec_packet->pkt->data[offset + byte_idx];
487 new ProtectedPacket()); 390 for (uint16_t bit_idx = 0; bit_idx < 8; ++bit_idx) {
488 // This wraps naturally with the sequence number. 391 if (packet_mask & (1 << (7 - bit_idx))) {
489 protected_packet->seq_num = 392 std::unique_ptr<ProtectedPacket> protected_packet(
490 static_cast<uint16_t>(seq_num_base + (byte_idx << 3) + bit_idx); 393 new ProtectedPacket());
491 protected_packet->pkt = nullptr; 394 // This wraps naturally with the sequence number.
492 // Note that |protected_pkt_list| is sorted (according to sequence 395 protected_packet->seq_num =
493 // number) by construction. 396 static_cast<uint16_t>(seq_num_base + (byte_idx << 3) + bit_idx);
494 fec_packet->protected_packets.push_back(std::move(protected_packet)); 397 protected_packet->pkt = nullptr;
398 fec_packet->protected_packets.push_back(std::move(protected_packet));
399 }
495 } 400 }
496 } 401 }
497 } 402 }
498 if (fec_packet->protected_packets.empty()) { 403 if (fec_packet->protected_packets.empty()) {
499 // All-zero packet mask; we can discard this FEC packet. 404 // All-zero packet mask; we can discard this FEC packet.
500 LOG(LS_WARNING) << "Received FEC packet has an all-zero packet mask."; 405 LOG(LS_WARNING) << "Received FEC packet has an all-zero packet mask.";
501 } else { 406 } else {
502 AssignRecoveredPackets(fec_packet.get(), recovered_packets); 407 AssignRecoveredPackets(recovered_packets, fec_packet.get());
503 // TODO(holmer): Consider replacing this with a binary search for the right 408 // TODO(holmer): Consider replacing this with a binary search for the right
504 // position, and then just insert the new packet. Would get rid of the sort. 409 // position, and then just insert the new packet. Would get rid of the sort.
505 // 410 //
506 // For correct decoding, |fec_packet_list_| does not necessarily 411 // For correct decoding, |received_fec_packets_| does not necessarily
507 // need to be sorted by sequence number (see decoding algorithm in 412 // need to be sorted by sequence number (see decoding algorithm in
508 // AttemptRecover()), but by keeping it sorted we try to recover the 413 // AttemptRecover()). By keeping it sorted we try to recover the
509 // oldest lost packets first. 414 // oldest lost packets first, however.
510 received_fec_packets_.push_back(std::move(fec_packet)); 415 received_fec_packets_.push_back(std::move(fec_packet));
511 received_fec_packets_.sort(SortablePacket::LessThan()); 416 received_fec_packets_.sort(SortablePacket::LessThan());
512 if (received_fec_packets_.size() > kMaxFecPackets) { 417 const size_t max_fec_packets = fec_header_reader_->MaxFecPackets();
418 if (received_fec_packets_.size() > max_fec_packets) {
513 received_fec_packets_.pop_front(); 419 received_fec_packets_.pop_front();
514 } 420 }
515 RTC_DCHECK_LE(received_fec_packets_.size(), kMaxFecPackets); 421 RTC_DCHECK_LE(received_fec_packets_.size(), max_fec_packets);
516 } 422 }
517 } 423 }
518 424
519 void ForwardErrorCorrection::AssignRecoveredPackets( 425 void ForwardErrorCorrection::AssignRecoveredPackets(
520 ReceivedFecPacket* fec_packet, 426 const RecoveredPacketList& recovered_packets,
521 const RecoveredPacketList* recovered_packets) { 427 ReceivedFecPacket* fec_packet) {
522 ProtectedPacketList* protected_packets = &fec_packet->protected_packets; 428 ProtectedPacketList* protected_packets = &fec_packet->protected_packets;
523 std::vector<RecoveredPacket*> recovered_protected_packets; 429 std::vector<RecoveredPacket*> recovered_protected_packets;
524 430
525 // Find intersection between the (sorted) containers |protected_packets| 431 // Find intersection between the (sorted) containers |protected_packets|
526 // and |recovered_packets|, i.e. all protected packets that have already 432 // and |recovered_packets|, i.e. all protected packets that have already
527 // been recovered. Update the corresponding protected packets to point to 433 // been recovered. Update the corresponding protected packets to point to
528 // the recovered packets. 434 // the recovered packets.
529 auto it_p = protected_packets->cbegin(); 435 auto it_p = protected_packets->cbegin();
530 auto it_r = recovered_packets->cbegin(); 436 auto it_r = recovered_packets.cbegin();
531 SortablePacket::LessThan less_than; 437 SortablePacket::LessThan less_than;
532 while (it_p != protected_packets->end() && it_r != recovered_packets->end()) { 438 while (it_p != protected_packets->end() && it_r != recovered_packets.end()) {
533 if (less_than(*it_p, *it_r)) { 439 if (less_than(*it_p, *it_r)) {
534 ++it_p; 440 ++it_p;
535 } else if (less_than(*it_r, *it_p)) { 441 } else if (less_than(*it_r, *it_p)) {
536 ++it_r; 442 ++it_r;
537 } else { // *it_p == *it_r. 443 } else { // *it_p == *it_r.
538 // This protected packet has already been recovered. 444 // This protected packet has already been recovered.
539 (*it_p)->pkt = (*it_r)->pkt; 445 (*it_p)->pkt = (*it_r)->pkt;
540 ++it_p; 446 ++it_p;
541 ++it_r; 447 ++it_r;
542 } 448 }
(...skipping 16 matching lines...) Expand all
559 if (!received_fec_packets_.empty()) { 465 if (!received_fec_packets_.empty()) {
560 uint16_t seq_num_diff = 466 uint16_t seq_num_diff =
561 abs(static_cast<int>(received_packet->seq_num) - 467 abs(static_cast<int>(received_packet->seq_num) -
562 static_cast<int>(received_fec_packets_.front()->seq_num)); 468 static_cast<int>(received_fec_packets_.front()->seq_num));
563 if (seq_num_diff > 0x3fff) { 469 if (seq_num_diff > 0x3fff) {
564 received_fec_packets_.pop_front(); 470 received_fec_packets_.pop_front();
565 } 471 }
566 } 472 }
567 473
568 if (received_packet->is_fec) { 474 if (received_packet->is_fec) {
569 InsertFecPacket(received_packet, recovered_packets); 475 InsertFecPacket(*recovered_packets, received_packet);
570 } else { 476 } else {
571 InsertMediaPacket(received_packet, recovered_packets); 477 InsertMediaPacket(recovered_packets, received_packet);
572 } 478 }
573 // Delete the received packet "wrapper". 479 // Delete the received packet "wrapper".
574 received_packets->pop_front(); 480 received_packets->pop_front();
575 } 481 }
576 RTC_DCHECK(received_packets->empty()); 482 RTC_DCHECK(received_packets->empty());
577 DiscardOldRecoveredPackets(recovered_packets); 483 DiscardOldRecoveredPackets(recovered_packets);
578 } 484 }
579 485
580 bool ForwardErrorCorrection::StartPacketRecovery( 486 bool ForwardErrorCorrection::StartPacketRecovery(
581 const ReceivedFecPacket* fec_packet, 487 const ReceivedFecPacket& fec_packet,
582 RecoveredPacket* recovered_packet) { 488 RecoveredPacket* recovered_packet) {
583 // This is the first packet which we try to recover with. 489 // Sanity check packet length.
584 const uint16_t ulp_header_size = fec_packet->pkt->data[0] & 0x40 490 if (fec_packet.pkt->length < fec_packet.fec_header_size) {
585 ? kUlpHeaderSizeLBitSet
586 : kUlpHeaderSizeLBitClear; // L bit set?
587 if (fec_packet->pkt->length <
588 static_cast<size_t>(kFecHeaderSize + ulp_header_size)) {
589 LOG(LS_WARNING) 491 LOG(LS_WARNING)
590 << "Truncated FEC packet doesn't contain room for ULP header."; 492 << "The FEC packet is truncated: it does not contain enough room "
493 << "for its own header.";
591 return false; 494 return false;
592 } 495 }
496 // Initialize recovered packet data.
593 recovered_packet->pkt = new Packet(); 497 recovered_packet->pkt = new Packet();
594 memset(recovered_packet->pkt->data, 0, IP_PACKET_SIZE); 498 memset(recovered_packet->pkt->data, 0, IP_PACKET_SIZE);
595 recovered_packet->returned = false; 499 recovered_packet->returned = false;
596 recovered_packet->was_recovered = true; 500 recovered_packet->was_recovered = true;
597 uint16_t protection_length = 501 // Copy bytes corresponding to minimum RTP header size.
598 ByteReader<uint16_t>::ReadBigEndian(&fec_packet->pkt->data[10]); 502 // Note that the sequence number and SSRC fields will be overwritten
599 if (protection_length > 503 // at the end of packet recovery.
600 std::min( 504 memcpy(&recovered_packet->pkt->data, fec_packet.pkt->data, kRtpHeaderSize);
601 sizeof(recovered_packet->pkt->data) - kRtpHeaderSize, 505 // Copy remaining FEC payload.
602 sizeof(fec_packet->pkt->data) - kFecHeaderSize - ulp_header_size)) { 506 if (fec_packet.protection_length >
603 LOG(LS_WARNING) << "Incorrect FEC protection length, dropping."; 507 std::min(sizeof(recovered_packet->pkt->data) - kRtpHeaderSize,
508 sizeof(fec_packet.pkt->data) - fec_packet.fec_header_size)) {
509 LOG(LS_WARNING) << "Incorrect protection length, dropping FEC packet.";
604 return false; 510 return false;
605 } 511 }
606 // Copy FEC payload, skipping the ULP header.
607 memcpy(&recovered_packet->pkt->data[kRtpHeaderSize], 512 memcpy(&recovered_packet->pkt->data[kRtpHeaderSize],
608 &fec_packet->pkt->data[kFecHeaderSize + ulp_header_size], 513 &fec_packet.pkt->data[fec_packet.fec_header_size],
609 protection_length); 514 fec_packet.protection_length);
610 // Copy the length recovery field.
611 memcpy(recovered_packet->length_recovery, &fec_packet->pkt->data[8], 2);
612 // Copy the first 2 bytes of the FEC header.
613 memcpy(recovered_packet->pkt->data, fec_packet->pkt->data, 2);
614 // Copy the 5th to 8th bytes of the FEC header.
615 memcpy(&recovered_packet->pkt->data[4], &fec_packet->pkt->data[4], 4);
616 // Set the SSRC field.
617 ByteWriter<uint32_t>::WriteBigEndian(&recovered_packet->pkt->data[8],
618 fec_packet->ssrc);
619 return true; 515 return true;
620 } 516 }
621 517
622 bool ForwardErrorCorrection::FinishPacketRecovery( 518 bool ForwardErrorCorrection::FinishPacketRecovery(
519 const ReceivedFecPacket& fec_packet,
623 RecoveredPacket* recovered_packet) { 520 RecoveredPacket* recovered_packet) {
624 // Set the RTP version to 2. 521 // Set the RTP version to 2.
625 recovered_packet->pkt->data[0] |= 0x80; // Set the 1st bit. 522 recovered_packet->pkt->data[0] |= 0x80; // Set the 1st bit.
626 recovered_packet->pkt->data[0] &= 0xbf; // Clear the 2nd bit. 523 recovered_packet->pkt->data[0] &= 0xbf; // Clear the 2nd bit.
627 524 // Recover the packet length, from temporary location.
525 recovered_packet->pkt->length =
526 ByteReader<uint16_t>::ReadBigEndian(&recovered_packet->pkt->data[2]) +
527 kRtpHeaderSize;
528 if (recovered_packet->pkt->length >
529 sizeof(recovered_packet->pkt->data) - kRtpHeaderSize) {
530 LOG(LS_WARNING) << "The recovered packet had a length larger than a "
531 << "typical IP packet, and is thus dropped.";
532 return false;
533 }
628 // Set the SN field. 534 // Set the SN field.
629 ByteWriter<uint16_t>::WriteBigEndian(&recovered_packet->pkt->data[2], 535 ByteWriter<uint16_t>::WriteBigEndian(&recovered_packet->pkt->data[2],
630 recovered_packet->seq_num); 536 recovered_packet->seq_num);
631 // Recover the packet length. 537 // Set the SSRC field.
632 recovered_packet->pkt->length = 538 ByteWriter<uint32_t>::WriteBigEndian(&recovered_packet->pkt->data[8],
633 ByteReader<uint16_t>::ReadBigEndian(recovered_packet->length_recovery) + 539 fec_packet.rtp_ssrc);
634 kRtpHeaderSize;
635 if (recovered_packet->pkt->length >
636 sizeof(recovered_packet->pkt->data) - kRtpHeaderSize) {
637 return false;
638 }
639
640 return true; 540 return true;
641 } 541 }
642 542
643 void ForwardErrorCorrection::XorPackets(const Packet* src, 543 void ForwardErrorCorrection::XorPackets(const Packet& src,
644 RecoveredPacket* dst) { 544 size_t src_offset,
645 // XOR with the first 2 bytes of the RTP header. 545 size_t payload_length,
646 for (uint32_t i = 0; i < 2; ++i) { 546 size_t dst_offset,
647 dst->pkt->data[i] ^= src->data[i]; 547 Packet* dst) {
648 } 548 // XOR the first 2 bytes of the header: V, P, X, CC, M, PT fields.
649 // XOR with the 5th to 8th bytes of the RTP header. 549 dst->data[0] ^= src.data[0];
650 for (uint32_t i = 4; i < 8; ++i) { 550 dst->data[1] ^= src.data[1];
651 dst->pkt->data[i] ^= src->data[i];
652 }
653 // XOR with the network-ordered payload size.
654 uint8_t media_payload_length[2];
655 ByteWriter<uint16_t>::WriteBigEndian(media_payload_length,
656 src->length - kRtpHeaderSize);
657 dst->length_recovery[0] ^= media_payload_length[0];
658 dst->length_recovery[1] ^= media_payload_length[1];
659 551
660 // XOR with RTP payload. 552 // XOR the length recovery field.
661 // TODO(marpan/ajm): Are we doing more XORs than required here? 553 uint8_t src_payload_length_network_order[2];
662 for (size_t i = kRtpHeaderSize; i < src->length; ++i) { 554 ByteWriter<uint16_t>::WriteBigEndian(src_payload_length_network_order,
663 dst->pkt->data[i] ^= src->data[i]; 555 src.length - kRtpHeaderSize);
556 dst->data[2] ^= src_payload_length_network_order[0];
557 dst->data[3] ^= src_payload_length_network_order[1];
558
559 // XOR the 5th to 8th bytes of the header: the timestamp field.
560 dst->data[4] ^= src.data[4];
561 dst->data[5] ^= src.data[5];
562 dst->data[6] ^= src.data[6];
563 dst->data[7] ^= src.data[7];
564
565 // Skip the 9th to 12th bytes of the header.
566
567 // XOR the payload.
568 RTC_DCHECK_LE(src_offset + payload_length, sizeof(src.data));
danilchap 2016/08/29 12:26:02 may be src.length/dst->length instead of sizeof to
brandtr 2016/08/30 07:12:40 This is a good idea, but I'll wait until a later C
569 RTC_DCHECK_LE(dst_offset + payload_length, sizeof(dst->data));
570 for (size_t i = 0; i < payload_length; ++i) {
571 dst->data[dst_offset + i] ^= src.data[src_offset + i];
664 } 572 }
665 } 573 }
666 574
667 bool ForwardErrorCorrection::RecoverPacket( 575 bool ForwardErrorCorrection::RecoverPacket(const ReceivedFecPacket& fec_packet,
668 const ReceivedFecPacket* fec_packet, 576 RecoveredPacket* recovered_packet) {
669 RecoveredPacket* rec_packet_to_insert) { 577 if (!StartPacketRecovery(fec_packet, recovered_packet)) {
670 if (!StartPacketRecovery(fec_packet, rec_packet_to_insert))
671 return false; 578 return false;
672 for (const auto& protected_packet : fec_packet->protected_packets) { 579 }
580 for (const auto& protected_packet : fec_packet.protected_packets) {
673 if (protected_packet->pkt == nullptr) { 581 if (protected_packet->pkt == nullptr) {
674 // This is the packet we're recovering. 582 // This is the packet we're recovering.
675 rec_packet_to_insert->seq_num = protected_packet->seq_num; 583 recovered_packet->seq_num = protected_packet->seq_num;
676 } else { 584 } else {
677 XorPackets(protected_packet->pkt, rec_packet_to_insert); 585 XorPackets(*protected_packet->pkt, kRtpHeaderSize,
586 protected_packet->pkt->length, kRtpHeaderSize,
587 recovered_packet->pkt);
678 } 588 }
679 } 589 }
680 if (!FinishPacketRecovery(rec_packet_to_insert)) 590 if (!FinishPacketRecovery(fec_packet, recovered_packet)) {
681 return false; 591 return false;
592 }
682 return true; 593 return true;
683 } 594 }
684 595
685 void ForwardErrorCorrection::AttemptRecover( 596 void ForwardErrorCorrection::AttemptRecovery(
686 RecoveredPacketList* recovered_packets) { 597 RecoveredPacketList* recovered_packets) {
687 auto fec_packet_it = received_fec_packets_.begin(); 598 auto fec_packet_it = received_fec_packets_.begin();
688 while (fec_packet_it != received_fec_packets_.end()) { 599 while (fec_packet_it != received_fec_packets_.end()) {
689 // Search for each FEC packet's protected media packets. 600 // Search for each FEC packet's protected media packets.
690 int packets_missing = NumCoveredPacketsMissing(fec_packet_it->get()); 601 int packets_missing = NumCoveredPacketsMissing(**fec_packet_it);
691 602
692 // We can only recover one packet with an FEC packet. 603 // We can only recover one packet with an FEC packet.
693 if (packets_missing == 1) { 604 if (packets_missing == 1) {
694 // Recovery possible. 605 // Recovery possible.
695 std::unique_ptr<RecoveredPacket> packet_to_insert(new RecoveredPacket()); 606 std::unique_ptr<RecoveredPacket> recovered_packet(new RecoveredPacket());
696 packet_to_insert->pkt = nullptr; 607 recovered_packet->pkt = nullptr;
697 if (!RecoverPacket(fec_packet_it->get(), packet_to_insert.get())) { 608 if (!RecoverPacket(**fec_packet_it, recovered_packet.get())) {
698 // Can't recover using this packet, drop it. 609 // Can't recover using this packet, drop it.
699 fec_packet_it = received_fec_packets_.erase(fec_packet_it); 610 fec_packet_it = received_fec_packets_.erase(fec_packet_it);
700 continue; 611 continue;
701 } 612 }
702 613
703 auto packet_to_insert_ptr = packet_to_insert.get(); 614 auto recovered_packet_ptr = recovered_packet.get();
704 // Add recovered packet to the list of recovered packets and update any 615 // Add recovered packet to the list of recovered packets and update any
705 // FEC packets covering this packet with a pointer to the data. 616 // FEC packets covering this packet with a pointer to the data.
706 // TODO(holmer): Consider replacing this with a binary search for the 617 // TODO(holmer): Consider replacing this with a binary search for the
707 // right position, and then just insert the new packet. Would get rid of 618 // right position, and then just insert the new packet. Would get rid of
708 // the sort. 619 // the sort.
709 recovered_packets->push_back(std::move(packet_to_insert)); 620 recovered_packets->push_back(std::move(recovered_packet));
710 recovered_packets->sort(SortablePacket::LessThan()); 621 recovered_packets->sort(SortablePacket::LessThan());
711 UpdateCoveringFecPackets(packet_to_insert_ptr); 622 UpdateCoveringFecPackets(*recovered_packet_ptr);
712 DiscardOldRecoveredPackets(recovered_packets); 623 DiscardOldRecoveredPackets(recovered_packets);
713 fec_packet_it = received_fec_packets_.erase(fec_packet_it); 624 fec_packet_it = received_fec_packets_.erase(fec_packet_it);
714 625
715 // A packet has been recovered. We need to check the FEC list again, as 626 // A packet has been recovered. We need to check the FEC list again, as
716 // this may allow additional packets to be recovered. 627 // this may allow additional packets to be recovered.
717 // Restart for first FEC packet. 628 // Restart for first FEC packet.
718 fec_packet_it = received_fec_packets_.begin(); 629 fec_packet_it = received_fec_packets_.begin();
719 } else if (packets_missing == 0) { 630 } else if (packets_missing == 0) {
720 // Either all protected packets arrived or have been recovered. We can 631 // Either all protected packets arrived or have been recovered. We can
721 // discard this FEC packet. 632 // discard this FEC packet.
722 fec_packet_it = received_fec_packets_.erase(fec_packet_it); 633 fec_packet_it = received_fec_packets_.erase(fec_packet_it);
723 } else { 634 } else {
724 fec_packet_it++; 635 fec_packet_it++;
725 } 636 }
726 } 637 }
727 } 638 }
728 639
729 int ForwardErrorCorrection::NumCoveredPacketsMissing( 640 int ForwardErrorCorrection::NumCoveredPacketsMissing(
730 const ReceivedFecPacket* fec_packet) { 641 const ReceivedFecPacket& fec_packet) {
731 int packets_missing = 0; 642 int packets_missing = 0;
732 for (const auto& protected_packet : fec_packet->protected_packets) { 643 for (const auto& protected_packet : fec_packet.protected_packets) {
733 if (protected_packet->pkt == nullptr) { 644 if (protected_packet->pkt == nullptr) {
734 ++packets_missing; 645 ++packets_missing;
735 if (packets_missing > 1) { 646 if (packets_missing > 1) {
736 break; // We can't recover more than one packet. 647 break; // We can't recover more than one packet.
737 } 648 }
738 } 649 }
739 } 650 }
740 return packets_missing; 651 return packets_missing;
741 } 652 }
742 653
743 void ForwardErrorCorrection::DiscardOldRecoveredPackets( 654 void ForwardErrorCorrection::DiscardOldRecoveredPackets(
744 RecoveredPacketList* recovered_packets) { 655 RecoveredPacketList* recovered_packets) {
745 while (recovered_packets->size() > kMaxMediaPackets) { 656 const size_t max_media_packets = fec_header_reader_->MaxMediaPackets();
657 while (recovered_packets->size() > max_media_packets) {
746 recovered_packets->pop_front(); 658 recovered_packets->pop_front();
747 } 659 }
748 RTC_DCHECK_LE(recovered_packets->size(), kMaxMediaPackets); 660 RTC_DCHECK_LE(recovered_packets->size(), max_media_packets);
749 } 661 }
750 662
751 uint16_t ForwardErrorCorrection::ParseSequenceNumber(uint8_t* packet) { 663 uint16_t ForwardErrorCorrection::ParseSequenceNumber(uint8_t* packet) {
752 return (packet[2] << 8) + packet[3]; 664 return (packet[2] << 8) + packet[3];
753 } 665 }
754 666
667 uint32_t ForwardErrorCorrection::ParseSsrc(uint8_t* packet) {
668 return (packet[8] << 24) + (packet[9] << 16) + (packet[10] << 8) + packet[11];
669 }
670
755 int ForwardErrorCorrection::DecodeFec( 671 int ForwardErrorCorrection::DecodeFec(
756 ReceivedPacketList* received_packets, 672 ReceivedPacketList* received_packets,
757 RecoveredPacketList* recovered_packets) { 673 RecoveredPacketList* recovered_packets) {
758 // TODO(marpan/ajm): can we check for multiple ULP headers, and return an 674 // TODO(marpan/ajm): can we check for multiple ULP headers, and return an
759 // error? 675 // error?
760 if (recovered_packets->size() == kMaxMediaPackets) { 676 const size_t max_media_packets = fec_header_reader_->MaxMediaPackets();
677 if (recovered_packets->size() == max_media_packets) {
761 const unsigned int seq_num_diff = 678 const unsigned int seq_num_diff =
762 abs(static_cast<int>(received_packets->front()->seq_num) - 679 abs(static_cast<int>(received_packets->front()->seq_num) -
763 static_cast<int>(recovered_packets->back()->seq_num)); 680 static_cast<int>(recovered_packets->back()->seq_num));
764 if (seq_num_diff > kMaxMediaPackets) { 681 if (seq_num_diff > max_media_packets) {
765 // A big gap in sequence numbers. The old recovered packets 682 // A big gap in sequence numbers. The old recovered packets
766 // are now useless, so it's safe to do a reset. 683 // are now useless, so it's safe to do a reset.
767 ResetState(recovered_packets); 684 ResetState(recovered_packets);
768 } 685 }
769 } 686 }
770 InsertPackets(received_packets, recovered_packets); 687 InsertPackets(received_packets, recovered_packets);
771 AttemptRecover(recovered_packets); 688 AttemptRecovery(recovered_packets);
772 return 0; 689 return 0;
773 } 690 }
774 691
775 size_t ForwardErrorCorrection::MaxPacketOverhead() const { 692 size_t ForwardErrorCorrection::MaxPacketOverhead() const {
776 return kFecHeaderSize + kUlpHeaderSizeLBitSet; 693 return fec_header_writer_->MaxPacketOverhead();
777 } 694 }
695
696 FecHeaderReader::FecHeaderReader(size_t max_media_packets,
697 size_t max_fec_packets)
698 : max_media_packets_(max_media_packets),
699 max_fec_packets_(max_fec_packets) {}
700
701 FecHeaderReader::~FecHeaderReader() = default;
702
703 size_t FecHeaderReader::MaxMediaPackets() const {
704 return max_media_packets_;
705 }
706
707 size_t FecHeaderReader::MaxFecPackets() const {
708 return max_fec_packets_;
709 }
710
711 FecHeaderWriter::FecHeaderWriter(size_t max_media_packets,
712 size_t max_fec_packets,
713 size_t max_packet_overhead)
714 : max_media_packets_(max_media_packets),
715 max_fec_packets_(max_fec_packets),
716 max_packet_overhead_(max_packet_overhead) {}
717
718 FecHeaderWriter::~FecHeaderWriter() = default;
719
720 size_t FecHeaderWriter::MaxMediaPackets() const {
721 return max_media_packets_;
722 }
723
724 size_t FecHeaderWriter::MaxFecPackets() const {
725 return max_fec_packets_;
726 }
727
728 size_t FecHeaderWriter::MaxPacketOverhead() const {
729 return max_packet_overhead_;
730 }
731
778 } // namespace webrtc 732 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698