OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2016 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 |
(...skipping 12 matching lines...) Expand all Loading... |
23 | 23 |
24 namespace webrtc { | 24 namespace webrtc { |
25 namespace rtp { | 25 namespace rtp { |
26 namespace { | 26 namespace { |
27 constexpr size_t kFixedHeaderSize = 12; | 27 constexpr size_t kFixedHeaderSize = 12; |
28 constexpr uint8_t kRtpVersion = 2; | 28 constexpr uint8_t kRtpVersion = 2; |
29 constexpr uint16_t kOneByteExtensionId = 0xBEDE; | 29 constexpr uint16_t kOneByteExtensionId = 0xBEDE; |
30 constexpr size_t kOneByteHeaderSize = 1; | 30 constexpr size_t kOneByteHeaderSize = 1; |
31 constexpr size_t kDefaultPacketSize = 1500; | 31 constexpr size_t kDefaultPacketSize = 1500; |
32 } // namespace | 32 } // namespace |
| 33 |
| 34 constexpr size_t Packet::kMaxExtensionHeaders; |
| 35 constexpr int Packet::kMinExtensionId; |
| 36 constexpr int Packet::kMaxExtensionId; |
| 37 |
33 // 0 1 2 3 | 38 // 0 1 2 3 |
34 // 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 | 39 // 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 |
35 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 40 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
36 // |V=2|P|X| CC |M| PT | sequence number | | 41 // |V=2|P|X| CC |M| PT | sequence number | |
37 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 42 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
38 // | timestamp | | 43 // | timestamp | |
39 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 44 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
40 // | synchronization source (SSRC) identifier | | 45 // | synchronization source (SSRC) identifier | |
41 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ | 46 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ |
42 // | Contributing source (CSRC) identifiers | | 47 // | Contributing source (CSRC) identifiers | |
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
266 payload_offset_ = kFixedHeaderSize + 4 * csrcs.size(); | 271 payload_offset_ = kFixedHeaderSize + 4 * csrcs.size(); |
267 WriteAt(0, (data()[0] & 0xF0) | csrcs.size()); | 272 WriteAt(0, (data()[0] & 0xF0) | csrcs.size()); |
268 size_t offset = kFixedHeaderSize; | 273 size_t offset = kFixedHeaderSize; |
269 for (uint32_t csrc : csrcs) { | 274 for (uint32_t csrc : csrcs) { |
270 ByteWriter<uint32_t>::WriteBigEndian(WriteAt(offset), csrc); | 275 ByteWriter<uint32_t>::WriteBigEndian(WriteAt(offset), csrc); |
271 offset += 4; | 276 offset += 4; |
272 } | 277 } |
273 buffer_.SetSize(payload_offset_); | 278 buffer_.SetSize(payload_offset_); |
274 } | 279 } |
275 | 280 |
| 281 bool Packet::HasRawExtension(int id) const { |
| 282 RTC_DCHECK_GE(id, kMinExtensionId); |
| 283 RTC_DCHECK_LE(id, kMaxExtensionId); |
| 284 return extension_entries_[id - 1].offset != 0; |
| 285 } |
| 286 |
| 287 rtc::ArrayView<const uint8_t> Packet::GetRawExtension(int id) const { |
| 288 RTC_DCHECK_GE(id, kMinExtensionId); |
| 289 RTC_DCHECK_LE(id, kMaxExtensionId); |
| 290 const ExtensionInfo& extension = extension_entries_[id - 1]; |
| 291 if (extension.offset == 0) |
| 292 return nullptr; |
| 293 return rtc::MakeArrayView(data() + extension.offset, extension.length); |
| 294 } |
| 295 |
| 296 bool Packet::SetRawExtension(int id, rtc::ArrayView<const uint8_t> data) { |
| 297 auto buffer = AllocateRawExtension(id, data.size()); |
| 298 if (buffer.empty()) |
| 299 return false; |
| 300 RTC_DCHECK_EQ(buffer.size(), data.size()); |
| 301 memcpy(buffer.data(), data.data(), data.size()); |
| 302 return true; |
| 303 } |
| 304 |
| 305 rtc::ArrayView<uint8_t> Packet::AllocateRawExtension(int id, size_t length) { |
| 306 RTC_DCHECK_GE(id, kMinExtensionId); |
| 307 RTC_DCHECK_LE(id, kMaxExtensionId); |
| 308 RTC_DCHECK_GE(length, 1); |
| 309 RTC_DCHECK_LE(length, 16); |
| 310 |
| 311 ExtensionInfo* extension_entry = &extension_entries_[id - 1]; |
| 312 if (extension_entry->offset != 0) { |
| 313 // Extension already reserved. Check if same length is used. |
| 314 if (extension_entry->length == length) |
| 315 return rtc::MakeArrayView(WriteAt(extension_entry->offset), length); |
| 316 |
| 317 LOG(LS_ERROR) << "Length mismatch for extension id " << id << " type " |
| 318 << static_cast<int>(extension_entry->type) << ": expected " |
| 319 << static_cast<int>(extension_entry->length) << ". received " |
| 320 << length; |
| 321 return nullptr; |
| 322 } |
| 323 if (payload_size_ > 0) { |
| 324 LOG(LS_ERROR) << "Can't add new extension id " << id |
| 325 << " after payload was set."; |
| 326 return nullptr; |
| 327 } |
| 328 if (padding_size_ > 0) { |
| 329 LOG(LS_ERROR) << "Can't add new extension id " << id |
| 330 << " after padding was set."; |
| 331 return nullptr; |
| 332 } |
| 333 |
| 334 size_t num_csrc = data()[0] & 0x0F; |
| 335 size_t extensions_offset = kFixedHeaderSize + (num_csrc * 4) + 4; |
| 336 size_t new_extensions_size = extensions_size_ + kOneByteHeaderSize + length; |
| 337 if (extensions_offset + new_extensions_size > capacity()) { |
| 338 LOG(LS_ERROR) |
| 339 << "Extension cannot be registered: Not enough space left in buffer."; |
| 340 return nullptr; |
| 341 } |
| 342 |
| 343 // All checks passed, write down the extension headers. |
| 344 if (extensions_size_ == 0) { |
| 345 RTC_DCHECK_EQ(payload_offset_, kFixedHeaderSize + (num_csrc * 4)); |
| 346 WriteAt(0, data()[0] | 0x10); // Set extension bit. |
| 347 // Profile specific ID always set to OneByteExtensionHeader. |
| 348 ByteWriter<uint16_t>::WriteBigEndian(WriteAt(extensions_offset - 4), |
| 349 kOneByteExtensionId); |
| 350 } |
| 351 |
| 352 WriteAt(extensions_offset + extensions_size_, (id << 4) | (length - 1)); |
| 353 |
| 354 extension_entry->offset = |
| 355 extensions_offset + extensions_size_ + kOneByteHeaderSize; |
| 356 extension_entry->length = length; |
| 357 extensions_size_ = new_extensions_size; |
| 358 |
| 359 // Update header length field. |
| 360 uint16_t extensions_words = (extensions_size_ + 3) / 4; // Wrap up to 32bit. |
| 361 ByteWriter<uint16_t>::WriteBigEndian(WriteAt(extensions_offset - 2), |
| 362 extensions_words); |
| 363 // Fill extension padding place with zeroes. |
| 364 size_t extension_padding_size = 4 * extensions_words - extensions_size_; |
| 365 memset(WriteAt(extensions_offset + extensions_size_), 0, |
| 366 extension_padding_size); |
| 367 payload_offset_ = extensions_offset + 4 * extensions_words; |
| 368 buffer_.SetSize(payload_offset_); |
| 369 return rtc::MakeArrayView(WriteAt(extension_entry->offset), length); |
| 370 } |
| 371 |
276 uint8_t* Packet::AllocatePayload(size_t size_bytes) { | 372 uint8_t* Packet::AllocatePayload(size_t size_bytes) { |
277 // Reset payload size to 0. If CopyOnWrite buffer_ was shared, this will cause | 373 // Reset payload size to 0. If CopyOnWrite buffer_ was shared, this will cause |
278 // reallocation and memcpy. Keeping just header reduces memcpy size. | 374 // reallocation and memcpy. Keeping just header reduces memcpy size. |
279 SetPayloadSize(0); | 375 SetPayloadSize(0); |
280 return SetPayloadSize(size_bytes); | 376 return SetPayloadSize(size_bytes); |
281 } | 377 } |
282 | 378 |
283 uint8_t* Packet::SetPayloadSize(size_t size_bytes) { | 379 uint8_t* Packet::SetPayloadSize(size_t size_bytes) { |
284 RTC_DCHECK_EQ(padding_size_, 0); | 380 RTC_DCHECK_EQ(padding_size_, 0); |
285 if (payload_offset_ + size_bytes > capacity()) { | 381 if (payload_offset_ + size_bytes > capacity()) { |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
453 << ", received " << static_cast<int>(extension.length); | 549 << ", received " << static_cast<int>(extension.length); |
454 return false; | 550 return false; |
455 } | 551 } |
456 *offset = extension.offset; | 552 *offset = extension.offset; |
457 return true; | 553 return true; |
458 } | 554 } |
459 } | 555 } |
460 return false; | 556 return false; |
461 } | 557 } |
462 | 558 |
463 bool Packet::AllocateExtension(ExtensionType type, | 559 rtc::ArrayView<uint8_t> Packet::AllocateExtension(ExtensionType type, |
464 uint8_t length, | 560 size_t length) { |
465 uint16_t* offset) { | |
466 uint8_t extension_id = ExtensionManager::kInvalidId; | |
467 ExtensionInfo* extension_entry = nullptr; | |
468 for (size_t i = 0; i < kMaxExtensionHeaders; ++i) { | 561 for (size_t i = 0; i < kMaxExtensionHeaders; ++i) { |
469 if (extension_entries_[i].type == type) { | 562 if (extension_entries_[i].type == type) { |
470 extension_id = i + 1; | 563 int extension_id = i + 1; |
471 extension_entry = &extension_entries_[i]; | 564 return AllocateRawExtension(extension_id, length); |
472 break; | |
473 } | 565 } |
474 } | 566 } |
475 | 567 // Extension not registered. |
476 if (!extension_entry) // Extension not registered. | 568 return nullptr; |
477 return false; | |
478 | |
479 if (extension_entry->length != 0) { // Already allocated. | |
480 if (length != extension_entry->length) { | |
481 LOG(LS_WARNING) << "Length mismatch for extension '" << type | |
482 << "': expected " << static_cast<int>(length) | |
483 << ", received " | |
484 << static_cast<int>(extension_entry->length); | |
485 return false; | |
486 } | |
487 *offset = extension_entry->offset; | |
488 return true; | |
489 } | |
490 | |
491 // Can't add new extension after payload/padding was set. | |
492 if (payload_size_ > 0) { | |
493 return false; | |
494 } | |
495 if (padding_size_ > 0) { | |
496 return false; | |
497 } | |
498 | |
499 RTC_DCHECK_GT(length, 0); | |
500 RTC_DCHECK_LE(length, 16); | |
501 | |
502 size_t num_csrc = data()[0] & 0x0F; | |
503 size_t extensions_offset = kFixedHeaderSize + (num_csrc * 4) + 4; | |
504 if (extensions_offset + extensions_size_ + kOneByteHeaderSize + length > | |
505 capacity()) { | |
506 LOG(LS_WARNING) << "Extension cannot be registered: " | |
507 "Not enough space left in buffer."; | |
508 return false; | |
509 } | |
510 | |
511 uint16_t new_extensions_size = | |
512 extensions_size_ + kOneByteHeaderSize + length; | |
513 uint16_t extensions_words = | |
514 (new_extensions_size + 3) / 4; // Wrap up to 32bit. | |
515 | |
516 // All checks passed, write down the extension. | |
517 if (extensions_size_ == 0) { | |
518 RTC_DCHECK_EQ(payload_offset_, kFixedHeaderSize + (num_csrc * 4)); | |
519 WriteAt(0, data()[0] | 0x10); // Set extension bit. | |
520 // Profile specific ID always set to OneByteExtensionHeader. | |
521 ByteWriter<uint16_t>::WriteBigEndian(WriteAt(extensions_offset - 4), | |
522 kOneByteExtensionId); | |
523 } | |
524 | |
525 WriteAt(extensions_offset + extensions_size_, | |
526 (extension_id << 4) | (length - 1)); | |
527 | |
528 extension_entry->length = length; | |
529 *offset = extensions_offset + kOneByteHeaderSize + extensions_size_; | |
530 extension_entry->offset = *offset; | |
531 extensions_size_ = new_extensions_size; | |
532 | |
533 // Update header length field. | |
534 ByteWriter<uint16_t>::WriteBigEndian(WriteAt(extensions_offset - 2), | |
535 extensions_words); | |
536 // Fill extension padding place with zeroes. | |
537 size_t extension_padding_size = 4 * extensions_words - extensions_size_; | |
538 memset(WriteAt(extensions_offset + extensions_size_), 0, | |
539 extension_padding_size); | |
540 payload_offset_ = extensions_offset + 4 * extensions_words; | |
541 buffer_.SetSize(payload_offset_); | |
542 return true; | |
543 } | 569 } |
544 | 570 |
545 uint8_t* Packet::WriteAt(size_t offset) { | 571 uint8_t* Packet::WriteAt(size_t offset) { |
546 return buffer_.data() + offset; | 572 return buffer_.data() + offset; |
547 } | 573 } |
548 | 574 |
549 void Packet::WriteAt(size_t offset, uint8_t byte) { | 575 void Packet::WriteAt(size_t offset, uint8_t byte) { |
550 buffer_.data()[offset] = byte; | 576 buffer_.data()[offset] = byte; |
551 } | 577 } |
552 | 578 |
553 } // namespace rtp | 579 } // namespace rtp |
554 } // namespace webrtc | 580 } // namespace webrtc |
OLD | NEW |