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/rtp_packet.h" | |
12 | |
13 #include <cstring> | |
14 | |
15 #include "webrtc/base/checks.h" | |
16 #include "webrtc/base/logging.h" | |
17 #include "webrtc/base/random.h" | |
18 #include "webrtc/common_types.h" | |
19 #include "webrtc/modules/rtp_rtcp/source/rtp_header_extension.h" | |
20 #include "webrtc/modules/rtp_rtcp/source/rtp_header_extensions.h" | |
21 #include "webrtc/modules/rtp_rtcp/source/byte_io.h" | |
22 | |
23 namespace webrtc { | |
24 namespace rtp { | |
25 namespace { | |
26 const size_t kFixedHeaderSize = 12; | |
27 const uint8_t kRtpVersion = 2; | |
28 const uint16_t kOneByteExtensionId = 0xBEDE; | |
29 const size_t kDefaultPacketSize = 1500; | |
30 } // namespace | |
31 // 0 1 2 3 | |
32 // 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 | |
33 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
34 // |V=2|P|X| CC |M| PT | sequence number | | |
35 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
36 // | timestamp | | |
37 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
38 // | synchronization source (SSRC) identifier | | |
39 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ | |
40 // | Contributing source (CSRC) identifiers | | |
41 // | .... | | |
42 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ | |
43 // |One-byte eXtensions id = 0xbede| length in 32bits | | |
44 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
45 // | Extensions | | |
46 // | .... | | |
47 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ | |
48 // | Payload | | |
49 // | .... : padding... | | |
50 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
51 // | padding | Padding size | | |
52 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
53 Packet::Packet(const ExtensionManager* extensions) | |
54 : extensions_(extensions), buffer_(kDefaultPacketSize) { | |
55 Clear(); | |
56 } | |
57 | |
58 Packet::Packet(const ExtensionManager* extensions, size_t capacity) | |
59 : extensions_(extensions), buffer_(capacity) { | |
60 RTC_DCHECK_GE(capacity, kFixedHeaderSize); | |
61 Clear(); | |
62 } | |
63 | |
64 Packet::~Packet() {} | |
65 | |
66 void Packet::IdentifyExtensions(const ExtensionManager* extensions) { | |
67 RTC_DCHECK(extensions); | |
68 extensions_ = extensions; | |
69 for (size_t i = 0; i < num_extensions_; ++i) { | |
70 uint8_t id = data()[extension_entries_[i].offset - 1] >> 4; | |
71 extension_entries_[i].type = extensions_->GetType(id); | |
72 } | |
73 } | |
74 | |
75 bool Packet::Parse(const uint8_t* buffer, size_t buffer_size) { | |
76 if (!ParseBuffer(buffer, buffer_size)) { | |
77 Clear(); | |
78 return false; | |
79 } | |
80 RTC_DCHECK_EQ(size(), buffer_size); | |
81 buffer_.SetData(buffer, buffer_size); | |
82 return true; | |
83 } | |
84 | |
85 bool Packet::Parse(rtc::Buffer buffer) { | |
86 if (!ParseBuffer(buffer.data(), buffer.size())) { | |
87 Clear(); | |
88 return false; | |
89 } | |
90 RTC_DCHECK_EQ(size(), buffer.size()); | |
91 buffer_ = std::move(buffer); | |
92 return true; | |
93 } | |
94 | |
95 bool Packet::Marker() const { | |
96 RTC_DCHECK_EQ(marker_, (data()[1] & 0x80) != 0); | |
97 return marker_; | |
98 } | |
99 | |
100 uint8_t Packet::PayloadType() const { | |
101 RTC_DCHECK_EQ(payload_type_, data()[1] & 0x7f); | |
102 return payload_type_; | |
103 } | |
104 | |
105 uint16_t Packet::SequenceNumber() const { | |
106 RTC_DCHECK_EQ(sequence_number_, | |
107 ByteReader<uint16_t>::ReadBigEndian(data() + 2)); | |
108 return sequence_number_; | |
109 } | |
110 | |
111 uint32_t Packet::Timestamp() const { | |
112 RTC_DCHECK_EQ(timestamp_, ByteReader<uint32_t>::ReadBigEndian(data() + 4)); | |
113 return timestamp_; | |
114 } | |
115 | |
116 uint32_t Packet::Ssrc() const { | |
117 RTC_DCHECK_EQ(ssrc_, ByteReader<uint32_t>::ReadBigEndian(data() + 8)); | |
118 return ssrc_; | |
119 } | |
120 | |
121 std::vector<uint32_t> Packet::Csrcs() const { | |
122 size_t num_csrc = data()[0] & 0x0F; | |
123 RTC_DCHECK_GE(capacity(), kFixedHeaderSize + num_csrc * 4); | |
124 std::vector<uint32_t> csrcs(num_csrc); | |
125 for (size_t i = 0; i < num_csrc; ++i) { | |
126 csrcs[i] = | |
127 ByteReader<uint32_t>::ReadBigEndian(&data()[kFixedHeaderSize + i * 4]); | |
128 } | |
129 return csrcs; | |
130 } | |
131 | |
132 void Packet::GetHeader(RTPHeader* header) const { | |
133 header->markerBit = Marker(); | |
134 header->payloadType = PayloadType(); | |
135 header->sequenceNumber = SequenceNumber(); | |
136 header->timestamp = Timestamp(); | |
137 header->ssrc = Ssrc(); | |
138 std::vector<uint32_t> csrcs = Csrcs(); | |
139 header->numCSRCs = csrcs.size(); | |
140 for (size_t i = 0; i < csrcs.size(); ++i) { | |
141 header->arrOfCSRCs[i] = csrcs[i]; | |
142 } | |
143 header->paddingLength = padding_size(); | |
144 header->headerLength = headers_size(); | |
145 header->payload_type_frequency = 0; | |
146 header->extension.hasTransmissionTimeOffset = | |
147 GetExtension<TransmissionOffset>( | |
148 &header->extension.transmissionTimeOffset); | |
149 header->extension.hasAbsoluteSendTime = | |
150 GetExtension<AbsoluteSendTime>(&header->extension.absoluteSendTime); | |
151 header->extension.hasTransportSequenceNumber = | |
152 GetExtension<TransportSequenceNumber>( | |
153 &header->extension.transportSequenceNumber); | |
154 header->extension.hasAudioLevel = GetExtension<AudioLevel>( | |
155 &header->extension.voiceActivity, &header->extension.audioLevel); | |
156 header->extension.hasVideoRotation = | |
157 GetExtension<VideoOrientation>(&header->extension.videoRotation); | |
158 } | |
159 | |
160 size_t Packet::headers_size() const { | |
161 return payload_offset_; | |
162 } | |
163 | |
164 size_t Packet::payload_size() const { | |
165 return payload_size_; | |
166 } | |
167 | |
168 size_t Packet::padding_size() const { | |
169 return padding_size_; | |
170 } | |
171 | |
172 const uint8_t* Packet::payload() const { | |
173 return data() + payload_offset_; | |
174 } | |
175 | |
176 size_t Packet::capacity() const { | |
177 return buffer_.size(); | |
terelius
2016/04/19 14:18:20
Whats the reason for changing to .size() instead o
| |
178 } | |
179 | |
180 size_t Packet::size() const { | |
181 return payload_offset_ + payload_size_ + padding_size_; | |
182 } | |
183 | |
184 const uint8_t* Packet::data() const { | |
185 return buffer_.data(); | |
186 } | |
187 | |
188 size_t Packet::FreeCapacity() const { | |
189 return capacity() - size(); | |
190 } | |
191 | |
192 size_t Packet::MaxPayloadSize() const { | |
193 return capacity() - payload_offset_; | |
194 } | |
195 | |
196 void Packet::CopyHeader(const Packet& packet) { | |
197 RTC_DCHECK_GE(capacity(), packet.headers_size()); | |
198 | |
199 marker_ = packet.marker_; | |
200 payload_type_ = packet.payload_type_; | |
201 sequence_number_ = packet.sequence_number_; | |
202 timestamp_ = packet.timestamp_; | |
203 ssrc_ = packet.ssrc_; | |
204 payload_offset_ = packet.payload_offset_; | |
205 num_extensions_ = packet.num_extensions_; | |
206 for (size_t i = 0; i < num_extensions_; ++i) { | |
207 extension_entries_[i] = packet.extension_entries_[i]; | |
208 } | |
209 extensions_size_ = packet.extensions_size_; | |
210 buffer_.SetData(packet.data(), packet.headers_size()); | |
211 // Reset payload and padding. | |
212 payload_size_ = 0; | |
213 padding_size_ = 0; | |
214 } | |
215 | |
216 void Packet::SetMarker(bool marker_bit) { | |
217 marker_ = marker_bit; | |
218 if (marker_) { | |
219 WriteAt(1, data()[1] | 0x80); | |
220 } else { | |
221 WriteAt(1, data()[1] & 0x7F); | |
222 } | |
223 } | |
224 | |
225 void Packet::SetPayloadType(uint8_t payload_type) { | |
226 RTC_DCHECK_LE(payload_type, 0x7Fu); | |
227 payload_type_ = payload_type; | |
228 WriteAt(1, (data()[1] & 0x80) | payload_type); | |
229 } | |
230 | |
231 void Packet::SetSequenceNumber(uint16_t seq_no) { | |
232 sequence_number_ = seq_no; | |
233 ByteWriter<uint16_t>::WriteBigEndian(WriteAt(2), seq_no); | |
234 } | |
235 | |
236 void Packet::SetTimestamp(uint32_t timestamp) { | |
237 timestamp_ = timestamp; | |
238 ByteWriter<uint32_t>::WriteBigEndian(WriteAt(4), timestamp); | |
239 } | |
240 | |
241 void Packet::SetSsrc(uint32_t ssrc) { | |
242 ssrc_ = ssrc; | |
243 ByteWriter<uint32_t>::WriteBigEndian(WriteAt(8), ssrc); | |
244 } | |
245 | |
246 void Packet::SetCsrcs(const std::vector<uint32_t>& csrcs) { | |
247 RTC_DCHECK_EQ(num_extensions_, 0u); | |
248 RTC_DCHECK_EQ(payload_size_, 0u); | |
249 RTC_DCHECK_EQ(padding_size_, 0u); | |
250 RTC_DCHECK_LE(csrcs.size(), 0x0fu); | |
251 RTC_DCHECK_LE(kFixedHeaderSize + 4 * csrcs.size(), capacity()); | |
252 payload_offset_ = kFixedHeaderSize + 4 * csrcs.size(); | |
253 WriteAt(0, (data()[0] & 0xF0) | csrcs.size()); | |
254 size_t offset = kFixedHeaderSize; | |
255 for (uint32_t csrc : csrcs) { | |
256 ByteWriter<uint32_t>::WriteBigEndian(WriteAt(offset), csrc); | |
257 offset += 4; | |
258 } | |
259 } | |
260 | |
261 uint8_t* Packet::AllocatePayload(size_t size_bytes) { | |
262 RTC_DCHECK_EQ(padding_size_, 0u); | |
263 if (payload_offset_ + size_bytes > capacity()) { | |
264 LOG(LS_WARNING) << "Cannot set payload, not enough space in buffer."; | |
265 return nullptr; | |
266 } | |
267 payload_size_ = size_bytes; | |
268 return WriteAt(payload_offset_); | |
269 } | |
270 | |
271 void Packet::SetPayloadSize(size_t size_bytes) { | |
272 RTC_DCHECK_EQ(padding_size_, 0u); | |
273 RTC_DCHECK_LE(size_bytes, payload_size_); | |
274 payload_size_ = size_bytes; | |
275 } | |
276 | |
277 bool Packet::SetPadding(uint8_t size_bytes, Random* random) { | |
278 RTC_DCHECK(random); | |
279 if (payload_offset_ + payload_size_ + size_bytes > capacity()) { | |
280 LOG(LS_WARNING) << "Cannot set padding size " << size_bytes << ", only " | |
281 << (capacity() - payload_offset_ - payload_size_) | |
282 << " bytes left in buffer."; | |
283 return false; | |
284 } | |
285 padding_size_ = size_bytes; | |
286 if (padding_size_ > 0) { | |
287 size_t padding_offset = payload_offset_ + payload_size_; | |
288 size_t padding_end = padding_offset + padding_size_; | |
289 for (size_t offset = padding_offset; offset < padding_end - 1; ++offset) { | |
290 WriteAt(offset, random->Rand<uint8_t>()); | |
291 } | |
292 WriteAt(padding_end - 1, padding_size_); | |
293 WriteAt(0, data()[0] | 0x20); // Set padding bit. | |
294 } else { | |
295 WriteAt(0, data()[0] & ~0x20); // Clear padding bit. | |
296 } | |
297 return true; | |
298 } | |
299 | |
300 void Packet::Clear() { | |
301 marker_ = false; | |
302 payload_type_ = 0; | |
303 sequence_number_ = 0; | |
304 timestamp_ = 0; | |
305 ssrc_ = 0; | |
306 payload_offset_ = kFixedHeaderSize; | |
307 payload_size_ = 0; | |
308 padding_size_ = 0; | |
309 num_extensions_ = 0; | |
310 extensions_size_ = 0; | |
311 | |
312 memset(WriteAt(0), 0, kFixedHeaderSize); | |
313 WriteAt(0, kRtpVersion << 6); | |
314 } | |
315 | |
316 bool Packet::ParseBuffer(const uint8_t* buffer, size_t size) { | |
317 if (size < kFixedHeaderSize) { | |
318 return false; | |
319 } | |
320 const uint8_t version = buffer[0] >> 6; | |
321 if (version != kRtpVersion) { | |
322 return false; | |
323 } | |
324 const bool has_padding = (buffer[0] & 0x20) != 0; | |
325 const bool has_extension = (buffer[0] & 0x10) != 0; | |
326 const uint8_t number_of_crcs = buffer[0] & 0x0f; | |
327 marker_ = (buffer[1] & 0x80) != 0; | |
328 payload_type_ = buffer[1] & 0x7f; | |
329 | |
330 sequence_number_ = ByteReader<uint16_t>::ReadBigEndian(&buffer[2]); | |
331 timestamp_ = ByteReader<uint32_t>::ReadBigEndian(&buffer[4]); | |
332 ssrc_ = ByteReader<uint32_t>::ReadBigEndian(&buffer[8]); | |
333 if (size < kFixedHeaderSize + number_of_crcs * 4) { | |
334 return false; | |
335 } | |
336 payload_offset_ = kFixedHeaderSize + number_of_crcs * 4; | |
337 | |
338 if (has_padding) { | |
339 padding_size_ = buffer[size - 1]; | |
340 if (padding_size_ == 0) { | |
341 LOG(LS_WARNING) << "Padding was set, but padding size is zero"; | |
342 return false; | |
343 } | |
344 } else { | |
345 padding_size_ = 0; | |
346 } | |
347 | |
348 num_extensions_ = 0; | |
349 extensions_size_ = 0; | |
350 if (has_extension) { | |
351 /* RTP header extension, RFC 3550. | |
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 | defined by profile | length | | |
356 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
357 | header extension | | |
358 | .... | | |
359 */ | |
360 size_t extension_offset = payload_offset_ + 4; | |
361 if (extension_offset > size) { | |
362 return false; | |
363 } | |
364 uint16_t profile = | |
365 ByteReader<uint16_t>::ReadBigEndian(&buffer[payload_offset_]); | |
366 size_t extensions_capacity = | |
367 ByteReader<uint16_t>::ReadBigEndian(&buffer[payload_offset_ + 2]); | |
368 extensions_capacity *= 4; | |
369 if (extension_offset + extensions_capacity > size) { | |
370 return false; | |
371 } | |
372 if (profile != kOneByteExtensionId) { | |
373 LOG(LS_WARNING) << "Unsupported rtp extension " << profile; | |
374 } else { | |
375 const size_t kOneByteHeaderSize = 1; | |
376 const uint8_t kPaddingId = 0; | |
377 const uint8_t kReservedId = 15; | |
378 while (extensions_size_ + kOneByteHeaderSize < extensions_capacity) { | |
379 uint8_t id = buffer[extension_offset + extensions_size_] >> 4; | |
380 if (id == kReservedId) { | |
381 break; | |
382 } else if (id == kPaddingId) { | |
383 extensions_size_++; | |
384 continue; | |
385 } | |
386 uint8_t length = | |
387 1 + (buffer[extension_offset + extensions_size_] & 0xf); | |
388 extensions_size_ += kOneByteHeaderSize; | |
389 if (num_extensions_ >= kMaxExtensionHeaders) { | |
390 LOG(LS_WARNING) << "Too many extensions."; | |
391 return false; | |
392 } | |
393 extension_entries_[num_extensions_].type = | |
394 extensions_ ? extensions_->GetType(id) | |
395 : ExtensionManager::kInvalidType; | |
396 extension_entries_[num_extensions_].length = length; | |
397 extension_entries_[num_extensions_].offset = | |
398 extension_offset + extensions_size_; | |
399 num_extensions_++; | |
400 extensions_size_ += length; | |
401 } | |
402 } | |
403 payload_offset_ = extension_offset + extensions_capacity; | |
404 } | |
405 | |
406 if (payload_offset_ + padding_size_ > size) { | |
407 return false; | |
408 } | |
409 payload_size_ = size - payload_offset_ - padding_size_; | |
410 return true; | |
411 } | |
412 | |
413 bool Packet::FindExtension(ExtensionType type, | |
414 uint8_t length, | |
415 uint16_t* offset) const { | |
416 RTC_DCHECK(offset); | |
417 for (size_t i = 0; i < num_extensions_; ++i) { | |
418 if (extension_entries_[i].type == type) { | |
419 RTC_CHECK_EQ(length, extension_entries_[i].length) | |
420 << "Length mismatch for extension '" << type << "'" | |
421 << "should be " << length << ", received " | |
422 << extension_entries_[i].length; | |
423 *offset = extension_entries_[i].offset; | |
424 return true; | |
425 } | |
426 } | |
427 return false; | |
428 } | |
429 | |
430 bool Packet::AllocateExtension(ExtensionType type, | |
431 uint8_t length, | |
432 uint16_t* offset) { | |
433 if (!extensions_) { | |
434 return false; | |
435 } | |
436 if (FindExtension(type, length, offset)) { | |
437 return true; | |
438 } | |
439 | |
440 // Can't add new extension after payload/padding was set. | |
441 if (payload_size_ > 0) { | |
442 return false; | |
443 } | |
444 if (padding_size_ > 0) { | |
445 return false; | |
446 } | |
447 | |
448 uint8_t extension_id = extensions_->GetId(type); | |
449 if (extension_id == ExtensionManager::kInvalidId) { | |
450 return false; | |
451 } | |
452 RTC_DCHECK_GT(length, 0u); | |
453 RTC_DCHECK_LE(length, 16u); | |
454 | |
455 size_t num_csrc = data()[0] & 0x0F; | |
456 size_t extensions_offset = kFixedHeaderSize + (num_csrc * 4) + 4; | |
457 const uint8_t kExtensionHeaderSize = 1; // Using one-byte extensions only. | |
458 if (extensions_offset + extensions_size_ + kExtensionHeaderSize + length > | |
459 capacity()) { | |
460 LOG(LS_WARNING) << "Extension cannot be registered: " | |
461 "Not enough space left in buffer."; | |
462 return false; | |
463 } | |
464 | |
465 uint16_t new_extensions_size = | |
466 extensions_size_ + kExtensionHeaderSize + length; | |
467 uint16_t extensions_words = | |
468 (new_extensions_size + 3) / 4; // Wrap up to 32bit. | |
469 if (extensions_words > 0xFFFF) { | |
470 LOG(LS_WARNING) << "Too much extension header data, exceeds 2^16 DWORDS."; | |
471 return false; | |
472 } | |
473 | |
474 // All checks passed, write down the extension. | |
475 if (num_extensions_ == 0) { | |
476 RTC_DCHECK_EQ(payload_offset_, kFixedHeaderSize + (num_csrc * 4)); | |
477 RTC_DCHECK_EQ(extensions_size_, 0); | |
478 WriteAt(0, data()[0] | 0x10); // Set extension bit. | |
479 // Profile specific ID always set to OneByteExtensionHeader. | |
480 ByteWriter<uint16_t>::WriteBigEndian(WriteAt(extensions_offset - 4), | |
481 kOneByteExtensionId); | |
482 } | |
483 | |
484 WriteAt(extensions_offset + extensions_size_, | |
485 (extension_id << 4) | (length - 1)); | |
486 RTC_DCHECK(num_extensions_ < kMaxExtensionHeaders); | |
terelius
2016/04/19 14:18:20
Why not use DCHECK_LT here?
| |
487 extension_entries_[num_extensions_].type = type; | |
488 extension_entries_[num_extensions_].length = length; | |
489 *offset = extensions_offset + kExtensionHeaderSize + extensions_size_; | |
490 extension_entries_[num_extensions_].offset = *offset; | |
491 ++num_extensions_; | |
492 extensions_size_ = new_extensions_size; | |
493 | |
494 // Update header length field. | |
495 ByteWriter<uint16_t>::WriteBigEndian(WriteAt(extensions_offset - 2), | |
496 extensions_words); | |
497 // Fill extension padding place with zeroes. | |
498 size_t extension_padding_size = 4 * extensions_words - extensions_size_; | |
499 memset(WriteAt(extensions_offset + extensions_size_), 0, | |
500 extension_padding_size); | |
501 payload_offset_ = extensions_offset + 4 * extensions_words; | |
502 return true; | |
503 } | |
504 | |
505 uint8_t* Packet::WriteAt(size_t offset) { | |
506 return buffer_.data() + offset; | |
507 } | |
508 | |
509 void Packet::WriteAt(size_t offset, uint8_t byte) { | |
510 buffer_.data()[offset] = byte; | |
511 } | |
512 | |
513 } // namespace rtp | |
514 } // namespace webrtc | |
OLD | NEW |