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 #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 received_fec_packets_() {} |
danilchap
2016/08/25 17:49:15
remove received_fec_packets_
initialize packet_mas
brandtr
2016/08/26 11:22:22
Done.
| |
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 |
136 // Unpack packet masks. Since the precomputed packet masks are tailored | |
danilchap
2016/08/25 17:49:15
while it might be interesting to know, code alread
brandtr
2016/08/26 11:22:22
The code still relies on the two versions of ULPFE
| |
137 // for ULPFEC, the required mask size is given by the two | |
138 // discrete ULPFEC options, i.e., 16 or 48 bits long. | |
151 const internal::PacketMaskTable mask_table(fec_mask_type, num_media_packets); | 139 const internal::PacketMaskTable mask_table(fec_mask_type, num_media_packets); |
152 | 140 packet_mask_size_ = internal::PacketMaskSize(num_media_packets); |
153 // -- Generate packet masks -- | 141 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, | 142 internal::GeneratePacketMasks(num_media_packets, num_fec_packets, |
156 num_important_packets, use_unequal_protection, | 143 num_important_packets, use_unequal_protection, |
157 mask_table, packet_mask_); | 144 mask_table, packet_masks_); |
158 | 145 |
159 int num_mask_bits = InsertZerosInBitMasks( | 146 // Adapt packet masks to missing media packets. |
160 media_packets, packet_mask_, num_mask_bytes, num_fec_packets); | 147 int num_mask_bits = InsertZerosInPacketMasks(media_packets, num_fec_packets); |
161 | |
162 if (num_mask_bits < 0) { | 148 if (num_mask_bits < 0) { |
163 return -1; | 149 return -1; |
164 } | 150 } |
165 l_bit = (static_cast<size_t>(num_mask_bits) > 8 * kMaskSizeLBitClear); | 151 packet_mask_size_ = internal::PacketMaskSize(num_mask_bits); |
166 if (l_bit) { | |
167 num_mask_bytes = kMaskSizeLBitSet; | |
168 } | |
169 | 152 |
170 GenerateFecBitStrings(media_packets, packet_mask_, num_fec_packets, l_bit); | 153 // Write FEC packets to |generated_fec_packets_|. |
171 GenerateFecUlpHeaders(media_packets, packet_mask_, num_fec_packets, l_bit); | 154 GenerateFecPayloads(media_packets, num_fec_packets); |
155 FinalizeFecHeaders(media_packets, num_fec_packets); | |
172 | 156 |
173 return 0; | 157 return 0; |
174 } | 158 } |
175 | 159 |
176 int ForwardErrorCorrection::NumFecPackets(int num_media_packets, | 160 int ForwardErrorCorrection::NumFecPackets(int num_media_packets, |
177 int protection_factor) { | 161 int protection_factor) { |
178 // Result in Q0 with an unsigned round. | 162 // Result in Q0 with an unsigned round. |
179 int num_fec_packets = (num_media_packets * protection_factor + (1 << 7)) >> 8; | 163 int num_fec_packets = (num_media_packets * protection_factor + (1 << 7)) >> 8; |
180 // Generate at least one FEC packet if we need protection. | 164 // Generate at least one FEC packet if we need protection. |
181 if (protection_factor > 0 && num_fec_packets == 0) { | 165 if (protection_factor > 0 && num_fec_packets == 0) { |
182 num_fec_packets = 1; | 166 num_fec_packets = 1; |
183 } | 167 } |
184 RTC_DCHECK_LE(num_fec_packets, num_media_packets); | 168 RTC_DCHECK_LE(num_fec_packets, num_media_packets); |
185 return num_fec_packets; | 169 return num_fec_packets; |
186 } | 170 } |
187 | 171 |
188 void ForwardErrorCorrection::GenerateFecBitStrings( | 172 void ForwardErrorCorrection::GenerateFecPayloads( |
189 const PacketList& media_packets, | 173 const PacketList& media_packets, |
190 uint8_t* packet_mask, | 174 size_t num_fec_packets) { |
191 int num_fec_packets, | |
192 bool l_bit) { | |
193 RTC_DCHECK(!media_packets.empty()); | 175 RTC_DCHECK(!media_packets.empty()); |
194 uint8_t media_payload_length[2]; | 176 for (size_t i = 0; i < num_fec_packets; ++i) { |
195 const int num_mask_bytes = l_bit ? kMaskSizeLBitSet : kMaskSizeLBitClear; | 177 Packet* const fec_packet = &generated_fec_packets_[i]; |
196 const uint16_t ulp_header_size = | 178 uint32_t pkt_mask_idx = i * packet_mask_size_; |
197 l_bit ? kUlpHeaderSizeLBitSet : kUlpHeaderSizeLBitClear; | 179 const size_t min_packet_mask_size = fec_header_writer_->MinPacketMaskSize( |
198 const uint16_t fec_rtp_offset = | 180 &packet_masks_[pkt_mask_idx], packet_mask_size_); |
199 kFecHeaderSize + ulp_header_size - kRtpHeaderSize; | 181 const size_t fec_header_size = |
182 fec_header_writer_->FecHeaderSize(min_packet_mask_size); | |
200 | 183 |
201 for (int i = 0; i < num_fec_packets; ++i) { | 184 uint32_t media_pkt_idx = 0; |
202 Packet* const fec_packet = &generated_fec_packets_[i]; | |
203 auto media_packets_it = media_packets.cbegin(); | 185 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); | 186 uint16_t prev_seq_num = ParseSequenceNumber((*media_packets_it)->data); |
208 while (media_packets_it != media_packets.end()) { | 187 while (media_packets_it != media_packets.end()) { |
209 // Each FEC packet has a multiple byte mask. Determine if this media | 188 Packet* const media_packet = media_packets_it->get(); |
210 // packet should be included in FEC packet i. | 189 // Should |media_packet| be protected by |fec_packet|? |
211 if (packet_mask[pkt_mask_idx] & (1 << (7 - media_pkt_idx))) { | 190 if (packet_masks_[pkt_mask_idx] & (1 << (7 - media_pkt_idx))) { |
212 Packet* media_packet = media_packets_it->get(); | 191 size_t media_payload_length = media_packet->length - kRtpHeaderSize; |
192 uint8_t media_payload_length_network_order[2]; | |
193 ByteWriter<uint16_t>::WriteBigEndian(media_payload_length_network_order, | |
194 media_payload_length); | |
213 | 195 |
214 // Assign network-ordered media payload length. | 196 bool first_protected_packet = (fec_packet->length == 0); |
215 ByteWriter<uint16_t>::WriteBigEndian( | 197 size_t fec_packet_length = fec_header_size + media_payload_length; |
216 media_payload_length, media_packet->length - kRtpHeaderSize); | 198 if (fec_packet_length > fec_packet->length) { |
217 | 199 // Recall that XORing with zero (which the FEC packets are prefilled |
218 fec_packet_length = media_packet->length + fec_rtp_offset; | 200 // with) is the identity operator, thus all prior XORs are |
219 // On the first protected packet, we don't need to XOR. | 201 // still correct even though we expand the packet length here. |
220 if (fec_packet->length == 0) { | 202 fec_packet->length = fec_packet_length; |
221 // Copy the first 2 bytes of the RTP header. Note that the E and L | 203 } |
222 // bits are overwritten in GenerateFecUlpHeaders. | 204 if (first_protected_packet) { |
205 // Write P, X, CC, M, and PT recovery fields. | |
206 // Note that bits 0, 1, and 16 are overwritten in FinalizeFecHeaders. | |
223 memcpy(&fec_packet->data[0], &media_packet->data[0], 2); | 207 memcpy(&fec_packet->data[0], &media_packet->data[0], 2); |
224 // Copy the 5th to 8th bytes of the RTP header (timestamp). | 208 // Write length recovery field. (This is a temporary location for |
209 // ULPFEC.) | |
210 memcpy(&fec_packet->data[2], media_payload_length_network_order, 2); | |
211 // Write timestamp recovery field. | |
225 memcpy(&fec_packet->data[4], &media_packet->data[4], 4); | 212 memcpy(&fec_packet->data[4], &media_packet->data[4], 4); |
226 // Copy network-ordered payload size. | 213 // Write payload. |
227 memcpy(&fec_packet->data[8], media_payload_length, 2); | 214 memcpy(&fec_packet->data[fec_header_size], |
228 | 215 &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 { | 216 } else { |
234 // XOR with the first 2 bytes of the RTP header. | 217 XorPackets(media_packet, kRtpHeaderSize, |
235 fec_packet->data[0] ^= media_packet->data[0]; | 218 fec_packet_length - fec_header_size, fec_header_size, |
236 fec_packet->data[1] ^= media_packet->data[1]; | 219 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 } | 220 } |
256 } | 221 } |
257 media_packets_it++; | 222 media_packets_it++; |
258 if (media_packets_it != media_packets.end()) { | 223 if (media_packets_it != media_packets.end()) { |
259 uint16_t seq_num = ParseSequenceNumber((*media_packets_it)->data); | 224 uint16_t seq_num = ParseSequenceNumber((*media_packets_it)->data); |
260 media_pkt_idx += static_cast<uint16_t>(seq_num - prev_seq_num); | 225 media_pkt_idx += static_cast<uint16_t>(seq_num - prev_seq_num); |
261 prev_seq_num = seq_num; | 226 prev_seq_num = seq_num; |
262 } | 227 } |
263 pkt_mask_idx += media_pkt_idx / 8; | 228 pkt_mask_idx += media_pkt_idx / 8; |
264 media_pkt_idx %= 8; | 229 media_pkt_idx %= 8; |
265 } | 230 } |
266 RTC_DCHECK_GT(fec_packet->length, 0u) | 231 RTC_DCHECK_GT(fec_packet->length, 0u) |
267 << "Packet mask is wrong or poorly designed."; | 232 << "Packet mask is wrong or poorly designed."; |
268 } | 233 } |
269 } | 234 } |
270 | 235 |
271 int ForwardErrorCorrection::InsertZerosInBitMasks( | 236 int ForwardErrorCorrection::InsertZerosInPacketMasks( |
272 const PacketList& media_packets, | 237 const PacketList& media_packets, |
273 uint8_t* packet_mask, | 238 size_t num_fec_packets) { |
274 int num_mask_bytes, | 239 size_t num_media_packets = media_packets.size(); |
275 int num_fec_packets) { | 240 if (num_media_packets <= 1) { |
276 if (media_packets.size() <= 1) { | 241 return num_media_packets; |
277 return media_packets.size(); | |
278 } | 242 } |
279 int last_seq_num = ParseSequenceNumber(media_packets.back()->data); | 243 uint16_t last_seq_num = ParseSequenceNumber(media_packets.back()->data); |
280 int first_seq_num = ParseSequenceNumber(media_packets.front()->data); | 244 uint16_t first_seq_num = ParseSequenceNumber(media_packets.front()->data); |
281 int total_missing_seq_nums = | 245 uint16_t total_missing_seq_nums = |
282 static_cast<uint16_t>(last_seq_num - first_seq_num) - | 246 static_cast<uint16_t>(last_seq_num - first_seq_num) - num_media_packets + |
283 media_packets.size() + 1; | 247 1; |
284 if (total_missing_seq_nums == 0) { | 248 if (total_missing_seq_nums == 0) { |
285 // All sequence numbers are covered by the packet mask. No zero insertion | 249 // All sequence numbers are covered by the packet mask. |
286 // required. | 250 // No zero insertion required. |
287 return media_packets.size(); | 251 return num_media_packets; |
288 } | 252 } |
289 // We can only protect 8 * kMaskSizeLBitSet packets. | 253 if (total_missing_seq_nums + num_media_packets > kUlpfecMaxMediaPackets) { |
290 if (total_missing_seq_nums + media_packets.size() > 8 * kMaskSizeLBitSet) | |
291 return -1; | 254 return -1; |
255 } | |
292 // Allocate the new mask. | 256 // Allocate the new mask. |
293 int new_mask_bytes = kMaskSizeLBitClear; | 257 size_t tmp_packet_mask_size = |
294 if (media_packets.size() + | 258 internal::PacketMaskSize(total_missing_seq_nums + num_media_packets); |
295 total_missing_seq_nums > 8 * kMaskSizeLBitClear) { | 259 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 | 260 |
300 auto media_packets_it = media_packets.cbegin(); | 261 auto media_packets_it = media_packets.cbegin(); |
301 uint16_t prev_seq_num = first_seq_num; | 262 uint16_t prev_seq_num = first_seq_num; |
302 ++media_packets_it; | 263 ++media_packets_it; |
303 | 264 |
304 // Insert the first column. | 265 // Insert the first column. |
305 internal::CopyColumn(tmp_packet_mask_, new_mask_bytes, packet_mask_, | 266 internal::CopyColumn(tmp_packet_masks_, tmp_packet_mask_size, packet_masks_, |
306 num_mask_bytes, num_fec_packets, 0, 0); | 267 packet_mask_size_, num_fec_packets, 0, 0); |
307 size_t new_bit_index = 1; | 268 size_t new_bit_index = 1; |
308 size_t old_bit_index = 1; | 269 size_t old_bit_index = 1; |
309 // Insert zeros in the bit mask for every hole in the sequence. | 270 // Insert zeros in the bit mask for every hole in the sequence. |
310 while (media_packets_it != media_packets.end()) { | 271 while (media_packets_it != media_packets.end()) { |
311 if (new_bit_index == 8 * kMaskSizeLBitSet) { | 272 if (new_bit_index == kUlpfecMaxMediaPackets) { |
312 // We can only cover up to 48 packets. | 273 // We can only cover up to 48 packets. |
313 break; | 274 break; |
314 } | 275 } |
315 uint16_t seq_num = ParseSequenceNumber((*media_packets_it)->data); | 276 uint16_t seq_num = ParseSequenceNumber((*media_packets_it)->data); |
316 const int num_zeros_to_insert = | 277 const int num_zeros_to_insert = |
317 static_cast<uint16_t>(seq_num - prev_seq_num - 1); | 278 static_cast<uint16_t>(seq_num - prev_seq_num - 1); |
318 if (num_zeros_to_insert > 0) { | 279 if (num_zeros_to_insert > 0) { |
319 internal::InsertZeroColumns(num_zeros_to_insert, tmp_packet_mask_, | 280 internal::InsertZeroColumns(num_zeros_to_insert, tmp_packet_masks_, |
320 new_mask_bytes, num_fec_packets, | 281 tmp_packet_mask_size, num_fec_packets, |
321 new_bit_index); | 282 new_bit_index); |
322 } | 283 } |
323 new_bit_index += num_zeros_to_insert; | 284 new_bit_index += num_zeros_to_insert; |
324 internal::CopyColumn(tmp_packet_mask_, new_mask_bytes, packet_mask_, | 285 internal::CopyColumn(tmp_packet_masks_, tmp_packet_mask_size, packet_masks_, |
325 num_mask_bytes, num_fec_packets, new_bit_index, | 286 packet_mask_size_, num_fec_packets, new_bit_index, |
326 old_bit_index); | 287 old_bit_index); |
327 ++new_bit_index; | 288 ++new_bit_index; |
328 ++old_bit_index; | 289 ++old_bit_index; |
329 prev_seq_num = seq_num; | 290 prev_seq_num = seq_num; |
330 ++media_packets_it; | 291 ++media_packets_it; |
331 } | 292 } |
332 if (new_bit_index % 8 != 0) { | 293 if (new_bit_index % 8 != 0) { |
333 // We didn't fill the last byte. Shift bits to correct position. | 294 // We didn't fill the last byte. Shift bits to correct position. |
334 for (uint16_t row = 0; row < num_fec_packets; ++row) { | 295 for (uint16_t row = 0; row < num_fec_packets; ++row) { |
335 int new_byte_index = row * new_mask_bytes + new_bit_index / 8; | 296 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)); | 297 tmp_packet_masks_[new_byte_index] <<= (7 - (new_bit_index % 8)); |
337 } | 298 } |
338 } | 299 } |
339 // Replace the old mask with the new. | 300 // Replace the old mask with the new. |
340 memcpy(packet_mask, tmp_packet_mask_, kMaskSizeLBitSet * num_fec_packets); | 301 memcpy(packet_masks_, tmp_packet_masks_, |
302 num_fec_packets * tmp_packet_mask_size); | |
341 return new_bit_index; | 303 return new_bit_index; |
342 } | 304 } |
343 | 305 |
344 void ForwardErrorCorrection::GenerateFecUlpHeaders( | 306 void ForwardErrorCorrection::FinalizeFecHeaders(const PacketList& media_packets, |
345 const PacketList& media_packets, | 307 size_t num_fec_packets) { |
346 uint8_t* packet_mask, | 308 for (size_t i = 0; i < num_fec_packets; ++i) { |
347 int num_fec_packets, | 309 fec_header_writer_->FinalizeFecHeader( |
348 bool l_bit) { | 310 media_packets, &packet_masks_[i * packet_mask_size_], packet_mask_size_, |
349 // -- Generate FEC and ULP headers -- | 311 &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 } | 312 } |
403 } | 313 } |
404 | 314 |
405 void ForwardErrorCorrection::ResetState( | 315 void ForwardErrorCorrection::ResetState( |
406 RecoveredPacketList* recovered_packets) { | 316 RecoveredPacketList* recovered_packets) { |
407 // Free the memory for any existing recovered packets, if the caller hasn't. | 317 // Free the memory for any existing recovered packets, if the caller hasn't. |
408 recovered_packets->clear(); | 318 recovered_packets->clear(); |
409 received_fec_packets_.clear(); | 319 received_fec_packets_.clear(); |
410 } | 320 } |
411 | 321 |
412 void ForwardErrorCorrection::InsertMediaPacket( | 322 void ForwardErrorCorrection::InsertMediaPacket( |
413 ReceivedPacket* received_packet, | 323 ReceivedPacket* received_packet, |
414 RecoveredPacketList* recovered_packets) { | 324 RecoveredPacketList* recovered_packets) { |
415 | |
416 // Search for duplicate packets. | 325 // Search for duplicate packets. |
417 for (const auto& recovered_packet : *recovered_packets) { | 326 for (const auto& recovered_packet : *recovered_packets) { |
418 if (received_packet->seq_num == recovered_packet->seq_num) { | 327 if (received_packet->seq_num == recovered_packet->seq_num) { |
419 // Duplicate packet, no need to add to list. | 328 // Duplicate packet, no need to add to list. |
420 // Delete duplicate media packet data. | 329 // Delete duplicate media packet data. |
421 received_packet->pkt = nullptr; | 330 received_packet->pkt = nullptr; |
422 return; | 331 return; |
423 } | 332 } |
424 } | 333 } |
425 | |
426 std::unique_ptr<RecoveredPacket> recovered_packet(new RecoveredPacket()); | 334 std::unique_ptr<RecoveredPacket> recovered_packet(new RecoveredPacket()); |
427 // This "recovered packet" was not recovered using parity packets. | 335 // This "recovered packet" was not recovered using parity packets. |
428 recovered_packet->was_recovered = false; | 336 recovered_packet->was_recovered = false; |
429 // This media packet has already been passed on. | 337 // This media packet has already been passed on. |
430 recovered_packet->returned = true; | 338 recovered_packet->returned = true; |
431 recovered_packet->seq_num = received_packet->seq_num; | 339 recovered_packet->seq_num = received_packet->seq_num; |
432 recovered_packet->pkt = received_packet->pkt; | 340 recovered_packet->pkt = received_packet->pkt; |
433 recovered_packet->pkt->length = received_packet->pkt->length; | 341 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 | 342 // 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. | 343 // position, and then just insert the new packet. Would get rid of the sort. |
344 RecoveredPacket* recovered_packet_ptr = recovered_packet.get(); | |
438 recovered_packets->push_back(std::move(recovered_packet)); | 345 recovered_packets->push_back(std::move(recovered_packet)); |
439 recovered_packets->sort(SortablePacket::LessThan()); | 346 recovered_packets->sort(SortablePacket::LessThan()); |
440 UpdateCoveringFecPackets(recovered_packet_ptr); | 347 UpdateCoveringFecPackets(recovered_packet_ptr); |
441 } | 348 } |
442 | 349 |
443 void ForwardErrorCorrection::UpdateCoveringFecPackets(RecoveredPacket* packet) { | 350 void ForwardErrorCorrection::UpdateCoveringFecPackets(RecoveredPacket* packet) { |
444 for (auto& fec_packet : received_fec_packets_) { | 351 for (auto& fec_packet : received_fec_packets_) { |
445 // Is this FEC packet protecting the media packet |packet|? | 352 // Is this FEC packet protecting the media packet |packet|? |
446 auto protected_it = std::lower_bound(fec_packet->protected_packets.begin(), | 353 auto protected_it = std::lower_bound(fec_packet->protected_packets.begin(), |
447 fec_packet->protected_packets.end(), | 354 fec_packet->protected_packets.end(), |
(...skipping 11 matching lines...) Expand all Loading... | |
459 ReceivedPacket* received_packet, | 366 ReceivedPacket* received_packet, |
460 const RecoveredPacketList* recovered_packets) { | 367 const RecoveredPacketList* recovered_packets) { |
461 // Check for duplicate. | 368 // Check for duplicate. |
462 for (const auto& existing_fec_packet : received_fec_packets_) { | 369 for (const auto& existing_fec_packet : received_fec_packets_) { |
463 if (received_packet->seq_num == existing_fec_packet->seq_num) { | 370 if (received_packet->seq_num == existing_fec_packet->seq_num) { |
464 // Delete duplicate FEC packet data. | 371 // Delete duplicate FEC packet data. |
465 received_packet->pkt = nullptr; | 372 received_packet->pkt = nullptr; |
466 return; | 373 return; |
467 } | 374 } |
468 } | 375 } |
469 | |
470 std::unique_ptr<ReceivedFecPacket> fec_packet(new ReceivedFecPacket()); | 376 std::unique_ptr<ReceivedFecPacket> fec_packet(new ReceivedFecPacket()); |
471 fec_packet->pkt = received_packet->pkt; | 377 fec_packet->pkt = received_packet->pkt; |
472 fec_packet->seq_num = received_packet->seq_num; | 378 fec_packet->seq_num = received_packet->seq_num; |
473 fec_packet->ssrc = received_packet->ssrc; | 379 fec_packet->rtp_ssrc = received_packet->ssrc; |
474 | 380 // Parse ULPFEC/FlexFEC header specific info. |
475 const uint16_t seq_num_base = | 381 bool ret = fec_header_reader_->ReadFecHeader(fec_packet.get()); |
476 ByteReader<uint16_t>::ReadBigEndian(&fec_packet->pkt->data[2]); | 382 if (!ret) { |
477 const uint16_t mask_size_bytes = (fec_packet->pkt->data[0] & 0x40) | 383 LOG(LS_WARNING) << "Malformed FEC header: dropping packet."; |
478 ? kMaskSizeLBitSet | 384 return; |
479 : kMaskSizeLBitClear; // L bit set? | 385 } |
480 | 386 // Parse packet mask from header and represent as protected packets. |
481 // Parse erasure code mask from ULP header and represent as protected packets. | 387 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) { | 388 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]; | 389 size_t offset = stream_packet_mask_info.second.offset; |
484 for (uint16_t bit_idx = 0; bit_idx < 8; ++bit_idx) { | 390 size_t size = stream_packet_mask_info.second.size; |
485 if (packet_mask & (1 << (7 - bit_idx))) { | 391 for (uint16_t byte_idx = 0; byte_idx < size; ++byte_idx) { |
486 std::unique_ptr<ProtectedPacket> protected_packet( | 392 uint8_t packet_mask = fec_packet->pkt->data[offset + byte_idx]; |
487 new ProtectedPacket()); | 393 for (uint16_t bit_idx = 0; bit_idx < 8; ++bit_idx) { |
488 // This wraps naturally with the sequence number. | 394 if (packet_mask & (1 << (7 - bit_idx))) { |
489 protected_packet->seq_num = | 395 std::unique_ptr<ProtectedPacket> protected_packet( |
490 static_cast<uint16_t>(seq_num_base + (byte_idx << 3) + bit_idx); | 396 new ProtectedPacket()); |
491 protected_packet->pkt = nullptr; | 397 // This wraps naturally with the sequence number. |
492 // Note that |protected_pkt_list| is sorted (according to sequence | 398 protected_packet->seq_num = |
493 // number) by construction. | 399 static_cast<uint16_t>(seq_num_base + (byte_idx << 3) + bit_idx); |
494 fec_packet->protected_packets.push_back(std::move(protected_packet)); | 400 protected_packet->pkt = nullptr; |
401 fec_packet->protected_packets.push_back(std::move(protected_packet)); | |
402 } | |
495 } | 403 } |
496 } | 404 } |
497 } | 405 } |
498 if (fec_packet->protected_packets.empty()) { | 406 if (fec_packet->protected_packets.empty()) { |
499 // All-zero packet mask; we can discard this FEC packet. | 407 // All-zero packet mask; we can discard this FEC packet. |
500 LOG(LS_WARNING) << "Received FEC packet has an all-zero packet mask."; | 408 LOG(LS_WARNING) << "Received FEC packet has an all-zero packet mask."; |
501 } else { | 409 } else { |
502 AssignRecoveredPackets(fec_packet.get(), recovered_packets); | 410 AssignRecoveredPackets(fec_packet.get(), recovered_packets); |
503 // TODO(holmer): Consider replacing this with a binary search for the right | 411 // 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. | 412 // position, and then just insert the new packet. Would get rid of the sort. |
505 // | 413 // |
506 // For correct decoding, |fec_packet_list_| does not necessarily | 414 // For correct decoding, |received_fec_packets_| does not necessarily |
507 // need to be sorted by sequence number (see decoding algorithm in | 415 // need to be sorted by sequence number (see decoding algorithm in |
508 // AttemptRecover()), but by keeping it sorted we try to recover the | 416 // AttemptRecover()). By keeping it sorted we try to recover the |
509 // oldest lost packets first. | 417 // oldest lost packets first, however. |
510 received_fec_packets_.push_back(std::move(fec_packet)); | 418 received_fec_packets_.push_back(std::move(fec_packet)); |
511 received_fec_packets_.sort(SortablePacket::LessThan()); | 419 received_fec_packets_.sort(SortablePacket::LessThan()); |
512 if (received_fec_packets_.size() > kMaxFecPackets) { | 420 const size_t max_fec_packets = fec_header_reader_->MaxFecPackets(); |
421 if (received_fec_packets_.size() > max_fec_packets) { | |
513 received_fec_packets_.pop_front(); | 422 received_fec_packets_.pop_front(); |
514 } | 423 } |
515 RTC_DCHECK_LE(received_fec_packets_.size(), kMaxFecPackets); | 424 RTC_DCHECK_LE(received_fec_packets_.size(), max_fec_packets); |
516 } | 425 } |
517 } | 426 } |
518 | 427 |
519 void ForwardErrorCorrection::AssignRecoveredPackets( | 428 void ForwardErrorCorrection::AssignRecoveredPackets( |
520 ReceivedFecPacket* fec_packet, | 429 ReceivedFecPacket* fec_packet, |
521 const RecoveredPacketList* recovered_packets) { | 430 const RecoveredPacketList* recovered_packets) { |
522 ProtectedPacketList* protected_packets = &fec_packet->protected_packets; | 431 ProtectedPacketList* protected_packets = &fec_packet->protected_packets; |
523 std::vector<RecoveredPacket*> recovered_protected_packets; | 432 std::vector<RecoveredPacket*> recovered_protected_packets; |
524 | 433 |
525 // Find intersection between the (sorted) containers |protected_packets| | 434 // Find intersection between the (sorted) containers |protected_packets| |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
571 InsertMediaPacket(received_packet, recovered_packets); | 480 InsertMediaPacket(received_packet, recovered_packets); |
572 } | 481 } |
573 // Delete the received packet "wrapper". | 482 // Delete the received packet "wrapper". |
574 received_packets->pop_front(); | 483 received_packets->pop_front(); |
575 } | 484 } |
576 RTC_DCHECK(received_packets->empty()); | 485 RTC_DCHECK(received_packets->empty()); |
577 DiscardOldRecoveredPackets(recovered_packets); | 486 DiscardOldRecoveredPackets(recovered_packets); |
578 } | 487 } |
579 | 488 |
580 bool ForwardErrorCorrection::StartPacketRecovery( | 489 bool ForwardErrorCorrection::StartPacketRecovery( |
581 const ReceivedFecPacket* fec_packet, | 490 ReceivedFecPacket* fec_packet, |
582 RecoveredPacket* recovered_packet) { | 491 RecoveredPacket* recovered_packet) const { |
583 // This is the first packet which we try to recover with. | 492 // Sanity check packet length. |
584 const uint16_t ulp_header_size = fec_packet->pkt->data[0] & 0x40 | 493 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) | 494 LOG(LS_WARNING) |
590 << "Truncated FEC packet doesn't contain room for ULP header."; | 495 << "The FEC packet is truncated: it does not contain enough room " |
496 << "for its own header."; | |
591 return false; | 497 return false; |
592 } | 498 } |
499 // Initialize recovered packet data. | |
593 recovered_packet->pkt = new Packet(); | 500 recovered_packet->pkt = new Packet(); |
594 memset(recovered_packet->pkt->data, 0, IP_PACKET_SIZE); | 501 memset(recovered_packet->pkt->data, 0, IP_PACKET_SIZE); |
595 recovered_packet->returned = false; | 502 recovered_packet->returned = false; |
596 recovered_packet->was_recovered = true; | 503 recovered_packet->was_recovered = true; |
597 uint16_t protection_length = | 504 // Copy bytes corresponding to minimum RTP header size. |
598 ByteReader<uint16_t>::ReadBigEndian(&fec_packet->pkt->data[10]); | 505 // Note that the sequence number and SSRC fields will be overwritten |
599 if (protection_length > | 506 // at the end of packet recovery. |
600 std::min( | 507 memcpy(&recovered_packet->pkt->data, fec_packet->pkt->data, kRtpHeaderSize); |
601 sizeof(recovered_packet->pkt->data) - kRtpHeaderSize, | 508 // Copy remaining FEC payload. |
602 sizeof(fec_packet->pkt->data) - kFecHeaderSize - ulp_header_size)) { | 509 if (fec_packet->protection_length > |
603 LOG(LS_WARNING) << "Incorrect FEC protection length, dropping."; | 510 std::min(sizeof(recovered_packet->pkt->data) - kRtpHeaderSize, |
511 sizeof(fec_packet->pkt->data) - fec_packet->fec_header_size)) { | |
512 LOG(LS_WARNING) << "Incorrect protection length, dropping FEC packet."; | |
604 return false; | 513 return false; |
605 } | 514 } |
606 // Copy FEC payload, skipping the ULP header. | |
607 memcpy(&recovered_packet->pkt->data[kRtpHeaderSize], | 515 memcpy(&recovered_packet->pkt->data[kRtpHeaderSize], |
608 &fec_packet->pkt->data[kFecHeaderSize + ulp_header_size], | 516 &fec_packet->pkt->data[fec_packet->fec_header_size], |
609 protection_length); | 517 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; | 518 return true; |
620 } | 519 } |
621 | 520 |
622 bool ForwardErrorCorrection::FinishPacketRecovery( | 521 bool ForwardErrorCorrection::FinishPacketRecovery( |
522 const ReceivedFecPacket* fec_packet, | |
623 RecoveredPacket* recovered_packet) { | 523 RecoveredPacket* recovered_packet) { |
624 // Set the RTP version to 2. | 524 // Set the RTP version to 2. |
625 recovered_packet->pkt->data[0] |= 0x80; // Set the 1st bit. | 525 recovered_packet->pkt->data[0] |= 0x80; // Set the 1st bit. |
626 recovered_packet->pkt->data[0] &= 0xbf; // Clear the 2nd bit. | 526 recovered_packet->pkt->data[0] &= 0xbf; // Clear the 2nd bit. |
627 | 527 // Recover the packet length, from temporary location. |
528 recovered_packet->pkt->length = | |
529 ByteReader<uint16_t>::ReadBigEndian(&recovered_packet->pkt->data[2]) + | |
530 kRtpHeaderSize; | |
531 if (recovered_packet->pkt->length > | |
532 sizeof(recovered_packet->pkt->data) - kRtpHeaderSize) { | |
533 LOG(LS_WARNING) << "The recovered packet had a length larger than a " | |
534 << "typical IP packet, and is thus dropped."; | |
535 return false; | |
536 } | |
628 // Set the SN field. | 537 // Set the SN field. |
629 ByteWriter<uint16_t>::WriteBigEndian(&recovered_packet->pkt->data[2], | 538 ByteWriter<uint16_t>::WriteBigEndian(&recovered_packet->pkt->data[2], |
630 recovered_packet->seq_num); | 539 recovered_packet->seq_num); |
631 // Recover the packet length. | 540 // Set the SSRC field. |
632 recovered_packet->pkt->length = | 541 ByteWriter<uint32_t>::WriteBigEndian(&recovered_packet->pkt->data[8], |
633 ByteReader<uint16_t>::ReadBigEndian(recovered_packet->length_recovery) + | 542 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; | 543 return true; |
641 } | 544 } |
642 | 545 |
643 void ForwardErrorCorrection::XorPackets(const Packet* src, | 546 void ForwardErrorCorrection::XorPackets(const Packet* src, |
644 RecoveredPacket* dst) { | 547 size_t src_offset, |
645 // XOR with the first 2 bytes of the RTP header. | 548 size_t payload_length, |
646 for (uint32_t i = 0; i < 2; ++i) { | 549 size_t dst_offset, |
647 dst->pkt->data[i] ^= src->data[i]; | 550 Packet* dst) { |
648 } | 551 // 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. | 552 dst->data[0] ^= src->data[0]; |
650 for (uint32_t i = 4; i < 8; ++i) { | 553 dst->data[1] ^= src->data[1]; |
651 dst->pkt->data[i] ^= src->data[i]; | 554 |
652 } | 555 // XOR the length recovery field. |
653 // XOR with the network-ordered payload size. | 556 uint8_t src_payload_length_network_order[2]; |
654 uint8_t media_payload_length[2]; | 557 ByteWriter<uint16_t>::WriteBigEndian(src_payload_length_network_order, |
655 ByteWriter<uint16_t>::WriteBigEndian(media_payload_length, | |
656 src->length - kRtpHeaderSize); | 558 src->length - kRtpHeaderSize); |
657 dst->length_recovery[0] ^= media_payload_length[0]; | 559 dst->data[2] ^= src_payload_length_network_order[0]; |
658 dst->length_recovery[1] ^= media_payload_length[1]; | 560 dst->data[3] ^= src_payload_length_network_order[1]; |
659 | 561 |
660 // XOR with RTP payload. | 562 // XOR the 5th to 8th bytes of the header: the timestamp field. |
661 // TODO(marpan/ajm): Are we doing more XORs than required here? | 563 dst->data[4] ^= src->data[4]; |
662 for (size_t i = kRtpHeaderSize; i < src->length; ++i) { | 564 dst->data[5] ^= src->data[5]; |
663 dst->pkt->data[i] ^= src->data[i]; | 565 dst->data[6] ^= src->data[6]; |
566 dst->data[7] ^= src->data[7]; | |
567 | |
568 // Skip the 9th to 12th bytes of the header. | |
569 | |
570 // XOR the payload. | |
571 RTC_DCHECK_LE(src_offset + payload_length, sizeof(src->data)); | |
572 RTC_DCHECK_LE(dst_offset + payload_length, sizeof(dst->data)); | |
573 for (size_t i = 0; i < payload_length; ++i) { | |
574 dst->data[dst_offset + i] ^= src->data[src_offset + i]; | |
664 } | 575 } |
665 } | 576 } |
666 | 577 |
667 bool ForwardErrorCorrection::RecoverPacket( | 578 bool ForwardErrorCorrection::RecoverPacket(ReceivedFecPacket* fec_packet, |
danilchap
2016/08/25 17:49:15
why fec_packet no longer const?
brandtr
2016/08/26 11:22:22
No idea. I've added constness in some places in th
| |
668 const ReceivedFecPacket* fec_packet, | 579 RecoveredPacket* recovered_packet) { |
669 RecoveredPacket* rec_packet_to_insert) { | 580 if (!StartPacketRecovery(fec_packet, recovered_packet)) { |
670 if (!StartPacketRecovery(fec_packet, rec_packet_to_insert)) | |
671 return false; | 581 return false; |
582 } | |
672 for (const auto& protected_packet : fec_packet->protected_packets) { | 583 for (const auto& protected_packet : fec_packet->protected_packets) { |
673 if (protected_packet->pkt == nullptr) { | 584 if (protected_packet->pkt == nullptr) { |
674 // This is the packet we're recovering. | 585 // This is the packet we're recovering. |
675 rec_packet_to_insert->seq_num = protected_packet->seq_num; | 586 recovered_packet->seq_num = protected_packet->seq_num; |
676 } else { | 587 } else { |
677 XorPackets(protected_packet->pkt, rec_packet_to_insert); | 588 XorPackets(protected_packet->pkt, kRtpHeaderSize, |
589 protected_packet->pkt->length, kRtpHeaderSize, | |
590 recovered_packet->pkt); | |
678 } | 591 } |
679 } | 592 } |
680 if (!FinishPacketRecovery(rec_packet_to_insert)) | 593 if (!FinishPacketRecovery(fec_packet, recovered_packet)) { |
681 return false; | 594 return false; |
595 } | |
682 return true; | 596 return true; |
683 } | 597 } |
684 | 598 |
685 void ForwardErrorCorrection::AttemptRecover( | 599 void ForwardErrorCorrection::AttemptRecovery( |
686 RecoveredPacketList* recovered_packets) { | 600 RecoveredPacketList* recovered_packets) { |
687 auto fec_packet_it = received_fec_packets_.begin(); | 601 auto fec_packet_it = received_fec_packets_.begin(); |
688 while (fec_packet_it != received_fec_packets_.end()) { | 602 while (fec_packet_it != received_fec_packets_.end()) { |
689 // Search for each FEC packet's protected media packets. | 603 // Search for each FEC packet's protected media packets. |
690 int packets_missing = NumCoveredPacketsMissing(fec_packet_it->get()); | 604 int packets_missing = NumCoveredPacketsMissing(fec_packet_it->get()); |
691 | 605 |
692 // We can only recover one packet with an FEC packet. | 606 // We can only recover one packet with an FEC packet. |
693 if (packets_missing == 1) { | 607 if (packets_missing == 1) { |
694 // Recovery possible. | 608 // Recovery possible. |
695 std::unique_ptr<RecoveredPacket> packet_to_insert(new RecoveredPacket()); | 609 std::unique_ptr<RecoveredPacket> recovered_packet(new RecoveredPacket()); |
696 packet_to_insert->pkt = nullptr; | 610 recovered_packet->pkt = nullptr; |
697 if (!RecoverPacket(fec_packet_it->get(), packet_to_insert.get())) { | 611 if (!RecoverPacket(fec_packet_it->get(), recovered_packet.get())) { |
698 // Can't recover using this packet, drop it. | 612 // Can't recover using this packet, drop it. |
699 fec_packet_it = received_fec_packets_.erase(fec_packet_it); | 613 fec_packet_it = received_fec_packets_.erase(fec_packet_it); |
700 continue; | 614 continue; |
701 } | 615 } |
702 | 616 |
703 auto packet_to_insert_ptr = packet_to_insert.get(); | 617 auto recovered_packet_ptr = recovered_packet.get(); |
704 // Add recovered packet to the list of recovered packets and update any | 618 // Add recovered packet to the list of recovered packets and update any |
705 // FEC packets covering this packet with a pointer to the data. | 619 // FEC packets covering this packet with a pointer to the data. |
706 // TODO(holmer): Consider replacing this with a binary search for the | 620 // 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 | 621 // right position, and then just insert the new packet. Would get rid of |
708 // the sort. | 622 // the sort. |
709 recovered_packets->push_back(std::move(packet_to_insert)); | 623 recovered_packets->push_back(std::move(recovered_packet)); |
710 recovered_packets->sort(SortablePacket::LessThan()); | 624 recovered_packets->sort(SortablePacket::LessThan()); |
711 UpdateCoveringFecPackets(packet_to_insert_ptr); | 625 UpdateCoveringFecPackets(recovered_packet_ptr); |
712 DiscardOldRecoveredPackets(recovered_packets); | 626 DiscardOldRecoveredPackets(recovered_packets); |
713 fec_packet_it = received_fec_packets_.erase(fec_packet_it); | 627 fec_packet_it = received_fec_packets_.erase(fec_packet_it); |
714 | 628 |
715 // A packet has been recovered. We need to check the FEC list again, as | 629 // A packet has been recovered. We need to check the FEC list again, as |
716 // this may allow additional packets to be recovered. | 630 // this may allow additional packets to be recovered. |
717 // Restart for first FEC packet. | 631 // Restart for first FEC packet. |
718 fec_packet_it = received_fec_packets_.begin(); | 632 fec_packet_it = received_fec_packets_.begin(); |
719 } else if (packets_missing == 0) { | 633 } else if (packets_missing == 0) { |
720 // Either all protected packets arrived or have been recovered. We can | 634 // Either all protected packets arrived or have been recovered. We can |
721 // discard this FEC packet. | 635 // discard this FEC packet. |
(...skipping 13 matching lines...) Expand all Loading... | |
735 if (packets_missing > 1) { | 649 if (packets_missing > 1) { |
736 break; // We can't recover more than one packet. | 650 break; // We can't recover more than one packet. |
737 } | 651 } |
738 } | 652 } |
739 } | 653 } |
740 return packets_missing; | 654 return packets_missing; |
741 } | 655 } |
742 | 656 |
743 void ForwardErrorCorrection::DiscardOldRecoveredPackets( | 657 void ForwardErrorCorrection::DiscardOldRecoveredPackets( |
744 RecoveredPacketList* recovered_packets) { | 658 RecoveredPacketList* recovered_packets) { |
745 while (recovered_packets->size() > kMaxMediaPackets) { | 659 const size_t max_media_packets = fec_header_reader_->MaxMediaPackets(); |
660 while (recovered_packets->size() > max_media_packets) { | |
746 recovered_packets->pop_front(); | 661 recovered_packets->pop_front(); |
747 } | 662 } |
748 RTC_DCHECK_LE(recovered_packets->size(), kMaxMediaPackets); | 663 RTC_DCHECK_LE(recovered_packets->size(), max_media_packets); |
749 } | 664 } |
750 | 665 |
751 uint16_t ForwardErrorCorrection::ParseSequenceNumber(uint8_t* packet) { | 666 uint16_t ForwardErrorCorrection::ParseSequenceNumber(uint8_t* packet) { |
752 return (packet[2] << 8) + packet[3]; | 667 return (packet[2] << 8) + packet[3]; |
753 } | 668 } |
754 | 669 |
670 uint32_t ForwardErrorCorrection::ParseSsrc(uint8_t* packet) { | |
671 return (packet[8] << 24) + (packet[9] << 16) + (packet[10] << 8) + packet[11]; | |
672 } | |
673 | |
755 int ForwardErrorCorrection::DecodeFec( | 674 int ForwardErrorCorrection::DecodeFec( |
756 ReceivedPacketList* received_packets, | 675 ReceivedPacketList* received_packets, |
757 RecoveredPacketList* recovered_packets) { | 676 RecoveredPacketList* recovered_packets) { |
758 // TODO(marpan/ajm): can we check for multiple ULP headers, and return an | 677 // TODO(marpan/ajm): can we check for multiple ULP headers, and return an |
759 // error? | 678 // error? |
760 if (recovered_packets->size() == kMaxMediaPackets) { | 679 const size_t max_media_packets = fec_header_reader_->MaxMediaPackets(); |
680 if (recovered_packets->size() == max_media_packets) { | |
761 const unsigned int seq_num_diff = | 681 const unsigned int seq_num_diff = |
762 abs(static_cast<int>(received_packets->front()->seq_num) - | 682 abs(static_cast<int>(received_packets->front()->seq_num) - |
763 static_cast<int>(recovered_packets->back()->seq_num)); | 683 static_cast<int>(recovered_packets->back()->seq_num)); |
764 if (seq_num_diff > kMaxMediaPackets) { | 684 if (seq_num_diff > max_media_packets) { |
765 // A big gap in sequence numbers. The old recovered packets | 685 // A big gap in sequence numbers. The old recovered packets |
766 // are now useless, so it's safe to do a reset. | 686 // are now useless, so it's safe to do a reset. |
767 ResetState(recovered_packets); | 687 ResetState(recovered_packets); |
768 } | 688 } |
769 } | 689 } |
770 InsertPackets(received_packets, recovered_packets); | 690 InsertPackets(received_packets, recovered_packets); |
771 AttemptRecover(recovered_packets); | 691 AttemptRecovery(recovered_packets); |
772 return 0; | 692 return 0; |
773 } | 693 } |
774 | 694 |
775 size_t ForwardErrorCorrection::MaxPacketOverhead() const { | 695 size_t ForwardErrorCorrection::MaxPacketOverhead() const { |
776 return kFecHeaderSize + kUlpHeaderSizeLBitSet; | 696 return fec_header_writer_->MaxPacketOverhead(); |
777 } | 697 } |
698 | |
699 FecHeaderReader::FecHeaderReader(size_t max_media_packets, | |
700 size_t max_fec_packets) | |
701 : max_media_packets_(max_media_packets), | |
702 max_fec_packets_(max_fec_packets) {} | |
703 | |
704 FecHeaderReader::~FecHeaderReader() = default; | |
705 | |
706 size_t FecHeaderReader::MaxMediaPackets() const { | |
707 return max_media_packets_; | |
708 } | |
709 | |
710 size_t FecHeaderReader::MaxFecPackets() const { | |
711 return max_fec_packets_; | |
712 } | |
713 | |
714 FecHeaderWriter::FecHeaderWriter(size_t max_media_packets, | |
715 size_t max_fec_packets, | |
716 size_t max_packet_overhead) | |
717 : max_media_packets_(max_media_packets), | |
718 max_fec_packets_(max_fec_packets), | |
719 max_packet_overhead_(max_packet_overhead) {} | |
720 | |
721 FecHeaderWriter::~FecHeaderWriter() = default; | |
722 | |
723 size_t FecHeaderWriter::MaxMediaPackets() const { | |
724 return max_media_packets_; | |
725 } | |
726 | |
727 size_t FecHeaderWriter::MaxFecPackets() const { | |
728 return max_fec_packets_; | |
729 } | |
730 | |
731 size_t FecHeaderWriter::MaxPacketOverhead() const { | |
732 return max_packet_overhead_; | |
733 } | |
734 | |
778 } // namespace webrtc | 735 } // namespace webrtc |
OLD | NEW |