OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. | |
3 * | |
4 * Use of this source code is governed by a BSD-style license | |
5 * that can be found in the LICENSE file in the root of the source | |
6 * tree. An additional intellectual property rights grant can be found | |
7 * in the file PATENTS. All contributing project authors may | |
8 * be found in the AUTHORS file in the root of the source tree. | |
9 */ | |
10 | |
11 #include "webrtc/modules/rtp_rtcp/source/flexfec_header_reader_writer.h" | |
12 | |
13 #include <string.h> | |
14 | |
15 #include <utility> | |
16 | |
17 #include "webrtc/base/checks.h" | |
18 #include "webrtc/base/logging.h" | |
19 #include "webrtc/modules/rtp_rtcp/source/byte_io.h" | |
20 #include "webrtc/modules/rtp_rtcp/source/forward_error_correction_internal.h" | |
21 | |
22 namespace webrtc { | |
23 | |
24 namespace { | |
25 | |
26 // Maximum number of media packets that can be protected in one batch. | |
27 constexpr size_t kMaxMediaPackets = 48; // Since we are reusing ULPFEC masks. | |
28 | |
29 // Maximum number of FEC packets stored inside ForwardErrorCorrection. | |
30 constexpr size_t kMaxFecPackets = kMaxMediaPackets; | |
31 | |
32 // Size (in bytes) of packet masks, given number of K bits set. | |
33 constexpr size_t kFlexfecPacketMaskSizes[] = {2, 6, 14}; | |
34 | |
35 // Size (in bytes) of part of header which is not packet mask specific. | |
36 constexpr size_t kBaseHeaderSize = 12; | |
37 | |
38 // Size (in bytes) of part of header which is stream specific. | |
39 constexpr size_t kStreamSpecificHeaderSize = 6; | |
40 | |
41 // Size (in bytes) of header, given the single stream packet mask size, i.e. | |
42 // the number of K-bits set. | |
43 constexpr size_t kHeaderSizes[] = { | |
44 kBaseHeaderSize + kStreamSpecificHeaderSize + kFlexfecPacketMaskSizes[0], | |
45 kBaseHeaderSize + kStreamSpecificHeaderSize + kFlexfecPacketMaskSizes[1], | |
46 kBaseHeaderSize + kStreamSpecificHeaderSize + kFlexfecPacketMaskSizes[2]}; | |
47 | |
48 // TODO(brandtr): Update this when we support multistream protection. | |
49 constexpr size_t kPacketMaskOffset = | |
50 kBaseHeaderSize + kStreamSpecificHeaderSize; | |
51 | |
52 // Here we count the K-bits as belonging to the packet mask. | |
53 // This can be used in conjunction with FlexfecHeaderWriter::MinPacketMaskSize, | |
54 // which calculates a bound on the needed packet mask size including K-bits, | |
55 // given a packet mask without K-bits. | |
56 size_t FlexfecHeaderSize(size_t packet_mask_size) { | |
57 RTC_DCHECK_LE(packet_mask_size, kFlexfecPacketMaskSizes[2]); | |
58 if (packet_mask_size <= kFlexfecPacketMaskSizes[0]) { | |
59 return kHeaderSizes[0]; | |
60 } else if (packet_mask_size <= kFlexfecPacketMaskSizes[1]) { | |
61 return kHeaderSizes[1]; | |
62 } | |
63 return kHeaderSizes[2]; | |
64 } | |
65 | |
66 } // namespace | |
67 | |
68 FlexfecHeaderReader::FlexfecHeaderReader() | |
69 : FecHeaderReader(kMaxMediaPackets, kMaxFecPackets) {} | |
70 | |
71 FlexfecHeaderReader::~FlexfecHeaderReader() = default; | |
72 | |
73 // TODO(brandtr): Update this function when we support flexible masks, | |
74 // retransmissions, and/or several protected SSRCs. | |
75 bool FlexfecHeaderReader::ReadFecHeader( | |
76 ForwardErrorCorrection::ReceivedFecPacket* fec_packet) const { | |
77 if (fec_packet->pkt->length <= kBaseHeaderSize + kStreamSpecificHeaderSize) { | |
78 LOG(LS_INFO) << "Discarding truncated FlexFEC packet."; | |
79 return false; | |
80 } | |
81 bool f_bit = (fec_packet->pkt->data[0] & 0x80) != 0; | |
82 if (f_bit) { | |
83 return false; | |
danilchap
2016/09/20 15:59:14
may be log as well.
brandtr
2016/09/21 09:23:23
So actually an F bit (or R bit) which is set is no
danilchap
2016/09/21 11:17:55
returning false means ReadFecHeader failed to read
brandtr
2016/09/21 12:53:11
Will leave as is. I'm not planning on handling the
| |
84 } | |
85 bool r_bit = (fec_packet->pkt->data[0] & 0x40) != 0; | |
86 if (r_bit) { | |
87 return false; | |
brandtr
2016/09/21 09:23:23
Ditto.
| |
88 } | |
89 uint8_t ssrc_count = | |
90 ByteReader<uint8_t>::ReadBigEndian(&fec_packet->pkt->data[8]); | |
91 if (ssrc_count != 1) { | |
92 return false; | |
brandtr
2016/09/21 09:23:23
Ditto.
| |
93 } | |
94 uint32_t protected_ssrc = | |
95 ByteReader<uint32_t>::ReadBigEndian(&fec_packet->pkt->data[12]); | |
96 uint16_t seq_num_base = | |
97 ByteReader<uint16_t>::ReadBigEndian(&fec_packet->pkt->data[16]); | |
98 | |
99 // Read packet mask and adapt it by removing the interleaved K bits. | |
100 // This destroys the FlexFEC standards compliance of the packet masks, | |
101 // but makes it compatible with the ULPFEC masks. | |
102 // TODO(brandtr): Store the adapted pack mask out-of-band, when the | |
103 // FEC packet classes have been refactored. | |
104 // | |
105 // We treat the mask parts as unsigned integers with host order endianness | |
106 // in order to simplify the bit shifting between bytes. | |
107 if (fec_packet->pkt->length < kHeaderSizes[0]) { | |
108 LOG(LS_INFO) << "Discarding truncated FlexFEC packet."; | |
109 return false; | |
110 } | |
111 uint8_t* const packet_mask = fec_packet->pkt->data + kPacketMaskOffset; | |
112 bool k_bit0 = (packet_mask[0] & 0x80) != 0; | |
113 uint16_t mask_part0 = ByteReader<uint16_t>::ReadBigEndian(&packet_mask[0]); | |
114 mask_part0 <<= 1; // Shift away K-bit 0 from adapted mask. | |
115 ByteWriter<uint16_t>::WriteBigEndian(&packet_mask[0], mask_part0); | |
116 size_t packet_mask_size; | |
117 if (k_bit0) { | |
118 packet_mask_size = kFlexfecPacketMaskSizes[0]; | |
119 } else { | |
120 if (fec_packet->pkt->length < kHeaderSizes[1]) { | |
121 return false; | |
122 } | |
123 bool k_bit1 = (packet_mask[2] & 0x80) != 0; | |
124 bool bit15 = (packet_mask[2] & 0x40) != 0; | |
125 if (bit15) { | |
126 packet_mask[1] |= 0x01; // Set bit 15 in adapted mask. | |
127 } | |
128 uint32_t mask_part1 = ByteReader<uint32_t>::ReadBigEndian(&packet_mask[2]); | |
129 mask_part1 <<= 2; // Shift away K-bit 1 and bit 15 from adapted mask. | |
130 ByteWriter<uint32_t>::WriteBigEndian(&packet_mask[2], mask_part1); | |
131 if (k_bit1) { | |
132 packet_mask_size = kFlexfecPacketMaskSizes[1]; | |
133 } else { | |
134 if (fec_packet->pkt->length < kHeaderSizes[2]) { | |
135 LOG(LS_INFO) << "Discarding truncated FlexFEC packet."; | |
136 return false; | |
137 } | |
138 bool k_bit2 = (packet_mask[6] & 0x80) != 0; | |
139 if (k_bit2) { | |
140 packet_mask_size = kFlexfecPacketMaskSizes[2]; | |
141 } else { | |
142 LOG(LS_INFO) << "Discarding FlexFEC packet with malformed header."; | |
143 return false; | |
144 } | |
145 // Copy bits 46 and 47. | |
146 uint8_t tail_bits = (packet_mask[6] >> 5) & 0x03; | |
147 packet_mask[5] |= tail_bits; | |
148 uint64_t mask_part2 = | |
149 ByteReader<uint64_t>::ReadBigEndian(&packet_mask[6]); | |
150 // Shift away K-bit 2, bit 46, and bit 47 from adapted mask. | |
151 mask_part2 <<= 3; | |
152 ByteWriter<uint64_t>::WriteBigEndian(&packet_mask[6], mask_part2); | |
153 } | |
154 } | |
155 | |
156 // Store "ULPFECized" packet mask info. | |
157 fec_packet->fec_header_size = FlexfecHeaderSize(packet_mask_size); | |
158 fec_packet->protected_ssrc = protected_ssrc; | |
159 fec_packet->seq_num_base = seq_num_base; | |
160 fec_packet->packet_mask_offset = kPacketMaskOffset; | |
161 fec_packet->packet_mask_size = packet_mask_size; | |
162 | |
163 // In FlexFEC, all media packets are protected in their entirety. | |
164 fec_packet->protection_length = | |
165 fec_packet->pkt->length - fec_packet->fec_header_size; | |
166 | |
167 return true; | |
168 } | |
169 | |
170 FlexfecHeaderWriter::FlexfecHeaderWriter() | |
171 : FecHeaderWriter(kMaxMediaPackets, kMaxFecPackets, kHeaderSizes[2]) {} | |
172 | |
173 FlexfecHeaderWriter::~FlexfecHeaderWriter() = default; | |
174 | |
175 size_t FlexfecHeaderWriter::MinPacketMaskSize(const uint8_t* packet_mask, | |
176 size_t packet_mask_size) const { | |
177 if (packet_mask_size == kUlpfecPacketMaskSizeLBitClear && | |
178 ((packet_mask[1] & 0x01) == 0)) { | |
179 // Packet mask is 16 bits long, with bit 15 clear. | |
180 // It can be used as is. | |
181 return kFlexfecPacketMaskSizes[0]; | |
182 } else if (packet_mask_size == kUlpfecPacketMaskSizeLBitClear) { | |
183 // Packet mask is 16 bits long, with bit 15 set. | |
184 // We must expand the packet mask with zeros in the FlexFEC header. | |
185 return kFlexfecPacketMaskSizes[1]; | |
186 } else if (packet_mask_size == kUlpfecPacketMaskSizeLBitSet && | |
187 ((packet_mask[5] & 0x03) == 0)) { | |
188 // Packet mask is 48 bits long, with bits 46 and 47 clear. | |
189 // It can be used as is. | |
190 return kFlexfecPacketMaskSizes[1]; | |
191 } else if (packet_mask_size == kUlpfecPacketMaskSizeLBitSet) { | |
192 // Packet mask is 48 bits long, with at least one of bits 46 and 47 set. | |
193 // We must expand it with zeros. | |
194 return kFlexfecPacketMaskSizes[2]; | |
195 } | |
196 RTC_NOTREACHED() << "Incorrect packet mask size: " << packet_mask_size << "."; | |
197 return kFlexfecPacketMaskSizes[2]; | |
198 } | |
199 | |
200 size_t FlexfecHeaderWriter::FecHeaderSize(size_t packet_mask_size) const { | |
201 return FlexfecHeaderSize(packet_mask_size); | |
202 } | |
203 | |
204 // This function adapts the precomputed ULPFEC packet masks to the | |
205 // FlexFEC header standard. Note that the header size is computed by | |
206 // FecHeaderSize(), so in this function we can be sure that we are | |
207 // writing in space that is intended for the header. | |
208 // | |
209 // TODO(brandtr): Update this function when we support offset-based masks, | |
210 // retransmissions, and protecting multiple SSRCs. | |
211 void FlexfecHeaderWriter::FinalizeFecHeader( | |
212 uint32_t ssrc, | |
213 uint16_t seq_num_base, | |
214 const uint8_t* packet_mask, | |
215 size_t packet_mask_size, | |
216 ForwardErrorCorrection::Packet* fec_packet) const { | |
217 fec_packet->data[0] &= 0x7f; // Clear F bit. | |
218 fec_packet->data[0] &= 0xbf; // Clear R bit. | |
219 // Write SSRC count, SSRC base, sequence number base. | |
220 ByteWriter<uint8_t>::WriteBigEndian(&fec_packet->data[8], 1U); | |
221 ByteWriter<uint32_t>::WriteBigEndian(&fec_packet->data[12], ssrc); | |
danilchap
2016/09/20 15:59:14
may be clear bytes [9,11] too. Or do you assume th
brandtr
2016/09/21 09:23:23
Currently we memset the entire packet to zero init
danilchap
2016/09/21 11:17:55
if you like this line to look more like neighbors,
brandtr
2016/09/21 12:53:11
Cool, didn't know about the <TYPE, NUMBER_OF_BYTES
| |
222 ByteWriter<uint16_t>::WriteBigEndian(&fec_packet->data[16], seq_num_base); | |
223 // Adapt ULPFEC packet mask to FlexFEC header. | |
224 // | |
225 // We treat the mask parts as unsigned integers with host order endianness | |
226 // in order to simplify the bit shifting between bytes. | |
227 uint8_t* const written_packet_mask = fec_packet->data + kPacketMaskOffset; | |
228 if (packet_mask_size == kUlpfecPacketMaskSizeLBitSet) { | |
229 // The packet mask is 48 bits long. | |
230 uint16_t tmp_mask_part0 = | |
231 ByteReader<uint16_t>::ReadBigEndian(&packet_mask[0]); | |
232 uint32_t tmp_mask_part1 = | |
233 ByteReader<uint32_t>::ReadBigEndian(&packet_mask[2]); | |
234 | |
235 tmp_mask_part0 >>= 1; // Shift, thus clearing K-bit 0. | |
236 ByteWriter<uint16_t>::WriteBigEndian(&written_packet_mask[0], | |
237 tmp_mask_part0); | |
238 tmp_mask_part1 >>= 2; // Shift, thus clearing K-bit 1 and bit 15. | |
239 ByteWriter<uint32_t>::WriteBigEndian(&written_packet_mask[2], | |
240 tmp_mask_part1); | |
241 bool bit15 = (packet_mask[1] & 0x01) != 0; | |
242 if (bit15) { | |
243 written_packet_mask[2] |= 0x40; // Set bit 15. | |
244 } | |
245 bool bit46 = (packet_mask[5] & 0x02) != 0; | |
246 bool bit47 = (packet_mask[5] & 0x01) != 0; | |
247 if (!bit46 && !bit47) { | |
248 written_packet_mask[2] |= 0x80; // Set K-bit 1. | |
249 } else { | |
250 memset(&written_packet_mask[6], 0, 8); // Clear all trailing bits. | |
251 written_packet_mask[6] |= 0x80; // Set K-bit 2. | |
252 if (bit46) { | |
253 written_packet_mask[6] |= 0x40; // Set bit 46. | |
254 } | |
255 if (bit47) { | |
256 written_packet_mask[6] |= 0x20; // Set bit 47. | |
257 } | |
258 } | |
259 } else if (packet_mask_size == kUlpfecPacketMaskSizeLBitClear) { | |
260 // The packet mask is 16 bits long. | |
261 uint16_t tmp_mask_part0 = | |
262 ByteReader<uint16_t>::ReadBigEndian(&packet_mask[0]); | |
263 | |
264 tmp_mask_part0 >>= 1; // Shift, thus clearing K-bit 0. | |
265 ByteWriter<uint16_t>::WriteBigEndian(&written_packet_mask[0], | |
266 tmp_mask_part0); | |
267 bool bit15 = (packet_mask[1] & 0x01) != 0; | |
268 if (!bit15) { | |
269 written_packet_mask[0] |= 0x80; // Set K-bit 0. | |
270 } else { | |
271 memset(&written_packet_mask[2], 0U, 4); // Clear all trailing bits. | |
272 written_packet_mask[2] |= 0x80; // Set K-bit 1. | |
273 written_packet_mask[2] |= 0x40; // Set bit 15. | |
274 } | |
275 } else { | |
276 RTC_NOTREACHED() << "Incorrect packet mask size: " << packet_mask_size | |
277 << "."; | |
278 } | |
279 } | |
280 | |
281 } // namespace webrtc | |
OLD | NEW |