| 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 |