Chromium Code Reviews| Index: webrtc/modules/rtp_rtcp/source/rtp_packet.cc |
| diff --git a/webrtc/modules/rtp_rtcp/source/rtp_packet.cc b/webrtc/modules/rtp_rtcp/source/rtp_packet.cc |
| index ec240a86359f2a970bf957887b268916493ffd1e..e6da175adee0fd3ebe9d9a482adeaa6d9f140e9a 100644 |
| --- a/webrtc/modules/rtp_rtcp/source/rtp_packet.cc |
| +++ b/webrtc/modules/rtp_rtcp/source/rtp_packet.cc |
| @@ -30,6 +30,9 @@ constexpr uint16_t kOneByteExtensionId = 0xBEDE; |
| constexpr size_t kOneByteHeaderSize = 1; |
| constexpr size_t kDefaultPacketSize = 1500; |
| } // namespace |
| + |
| +constexpr size_t Packet::kMaxExtensionHeaders; |
|
nisse-webrtc
2017/04/03 09:38:00
Why is this needed?
(And not part of this cl, bu
danilchap
2017/04/03 10:57:00
In theory - to make program well-formed.
In practi
nisse-webrtc
2017/04/03 11:21:19
The FAQ entry talks about static const, but here w
danilchap
2017/04/03 12:10:53
longer story:
you can get away without this constr
|
| + |
| // 0 1 2 3 |
| // 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 |
| // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| @@ -273,6 +276,97 @@ void Packet::SetCsrcs(const std::vector<uint32_t>& csrcs) { |
| buffer_.SetSize(payload_offset_); |
| } |
| +bool Packet::HasRawExtension(int id) const { |
| + RTC_DCHECK_GT(id, 0); |
|
nisse-webrtc
2017/04/03 09:38:00
I think it's unusual and confusing with a exclusiv
danilchap
2017/04/03 10:57:00
Good point. It is also bad idea to use kMaxExtensi
|
| + RTC_DCHECK_LE(id, kMaxExtensionHeaders); |
| + return extension_entries_[id - 1].offset != 0; |
| +} |
| + |
| +rtc::ArrayView<const uint8_t> Packet::GetRawExtension(int id) const { |
| + RTC_DCHECK_GT(id, 0); |
| + RTC_DCHECK_LE(id, kMaxExtensionHeaders); |
| + const ExtensionInfo& extension = extension_entries_[id - 1]; |
| + if (extension.offset == 0) |
| + return nullptr; |
| + return rtc::MakeArrayView(data() + extension.offset, extension.length); |
| +} |
| + |
| +bool Packet::SetRawExtension(int id, rtc::ArrayView<const uint8_t> data) { |
| + auto buffer = AllocateRawExtension(id, data.size()); |
| + if (buffer.empty()) |
| + return false; |
| + RTC_DCHECK_EQ(buffer.size(), data.size()); |
| + memcpy(buffer.data(), data.data(), data.size()); |
| + return true; |
| +} |
| + |
| +rtc::ArrayView<uint8_t> Packet::AllocateRawExtension(int id, size_t length) { |
| + RTC_DCHECK_GT(id, 0); |
| + RTC_DCHECK_LE(id, kMaxExtensionHeaders); |
| + RTC_DCHECK_GT(length, 0); |
| + RTC_DCHECK_LE(length, 16); |
| + |
| + ExtensionInfo* extension_entry = &extension_entries_[id - 1]; |
| + if (extension_entry->offset != 0) { |
| + // Extension already reserved. Check if same length is used. |
| + if (extension_entry->length == length) |
| + return rtc::MakeArrayView(WriteAt(extension_entry->offset), length); |
| + |
| + LOG(LS_ERROR) << "Length mismatch for extension id " << id << " type " |
| + << static_cast<int>(extension_entry->type) << ": expected " |
| + << static_cast<int>(extension_entry->length) << ". received " |
| + << length; |
| + return nullptr; |
| + } |
| + if (payload_size_ > 0) { |
| + LOG(LS_ERROR) << "Can't add new extension id " << id |
| + << " after payload was set."; |
| + return nullptr; |
| + } |
| + if (padding_size_ > 0) { |
| + LOG(LS_ERROR) << "Can't add new extension id " << id |
| + << " after padding was set."; |
| + return nullptr; |
| + } |
| + |
| + size_t num_csrc = data()[0] & 0x0F; |
| + size_t extensions_offset = kFixedHeaderSize + (num_csrc * 4) + 4; |
| + size_t new_extensions_size = extensions_size_ + kOneByteHeaderSize + length; |
| + if (extensions_offset + new_extensions_size > capacity()) { |
| + LOG(LS_ERROR) |
| + << "Extension cannot be registered: Not enough space left in buffer."; |
| + return nullptr; |
| + } |
| + |
| + // All checks passed, write down the extension headers. |
| + if (extensions_size_ == 0) { |
| + RTC_DCHECK_EQ(payload_offset_, kFixedHeaderSize + (num_csrc * 4)); |
| + WriteAt(0, data()[0] | 0x10); // Set extension bit. |
| + // Profile specific ID always set to OneByteExtensionHeader. |
| + ByteWriter<uint16_t>::WriteBigEndian(WriteAt(extensions_offset - 4), |
| + kOneByteExtensionId); |
| + } |
| + |
| + WriteAt(extensions_offset + extensions_size_, (id << 4) | (length - 1)); |
| + |
| + extension_entry->offset = |
| + extensions_offset + extensions_size_ + kOneByteHeaderSize; |
| + extension_entry->length = length; |
| + extensions_size_ = new_extensions_size; |
| + |
| + // Update header length field. |
| + uint16_t extensions_words = (extensions_size_ + 3) / 4; // Wrap up to 32bit. |
| + ByteWriter<uint16_t>::WriteBigEndian(WriteAt(extensions_offset - 2), |
| + extensions_words); |
| + // Fill extension padding place with zeroes. |
| + size_t extension_padding_size = 4 * extensions_words - extensions_size_; |
| + memset(WriteAt(extensions_offset + extensions_size_), 0, |
| + extension_padding_size); |
| + payload_offset_ = extensions_offset + 4 * extensions_words; |
| + buffer_.SetSize(payload_offset_); |
| + return rtc::MakeArrayView(WriteAt(extension_entry->offset), length); |
| +} |
| + |
| uint8_t* Packet::AllocatePayload(size_t size_bytes) { |
| // Reset payload size to 0. If CopyOnWrite buffer_ was shared, this will cause |
| // reallocation and memcpy. Keeping just header reduces memcpy size. |
| @@ -463,83 +557,18 @@ bool Packet::FindExtension(ExtensionType type, |
| bool Packet::AllocateExtension(ExtensionType type, |
|
nisse-webrtc
2017/04/03 09:38:00
For consistency, add an AllocateExtension method w
danilchap
2017/04/03 10:57:00
this is a private function, so can just replace it
|
| uint8_t length, |
| uint16_t* offset) { |
| - uint8_t extension_id = ExtensionManager::kInvalidId; |
| - ExtensionInfo* extension_entry = nullptr; |
| for (size_t i = 0; i < kMaxExtensionHeaders; ++i) { |
| if (extension_entries_[i].type == type) { |
| - extension_id = i + 1; |
| - extension_entry = &extension_entries_[i]; |
| - break; |
| - } |
| - } |
| - |
| - if (!extension_entry) // Extension not registered. |
| - return false; |
| - |
| - if (extension_entry->length != 0) { // Already allocated. |
| - if (length != extension_entry->length) { |
| - LOG(LS_WARNING) << "Length mismatch for extension '" << type |
| - << "': expected " << static_cast<int>(length) |
| - << ", received " |
| - << static_cast<int>(extension_entry->length); |
| - return false; |
| + int extension_id = i + 1; |
| + auto buffer = AllocateRawExtension(extension_id, length); |
| + if (buffer.empty()) |
| + return false; |
| + *offset = buffer.data() - WriteAt(0); |
| + return true; |
| } |
| - *offset = extension_entry->offset; |
| - return true; |
| - } |
| - |
| - // Can't add new extension after payload/padding was set. |
| - if (payload_size_ > 0) { |
| - return false; |
| - } |
| - if (padding_size_ > 0) { |
| - return false; |
| - } |
| - |
| - RTC_DCHECK_GT(length, 0); |
| - RTC_DCHECK_LE(length, 16); |
| - |
| - size_t num_csrc = data()[0] & 0x0F; |
| - size_t extensions_offset = kFixedHeaderSize + (num_csrc * 4) + 4; |
| - if (extensions_offset + extensions_size_ + kOneByteHeaderSize + length > |
| - capacity()) { |
| - LOG(LS_WARNING) << "Extension cannot be registered: " |
| - "Not enough space left in buffer."; |
| - return false; |
| } |
| - |
| - uint16_t new_extensions_size = |
| - extensions_size_ + kOneByteHeaderSize + length; |
| - uint16_t extensions_words = |
| - (new_extensions_size + 3) / 4; // Wrap up to 32bit. |
| - |
| - // All checks passed, write down the extension. |
| - if (extensions_size_ == 0) { |
| - RTC_DCHECK_EQ(payload_offset_, kFixedHeaderSize + (num_csrc * 4)); |
| - WriteAt(0, data()[0] | 0x10); // Set extension bit. |
| - // Profile specific ID always set to OneByteExtensionHeader. |
| - ByteWriter<uint16_t>::WriteBigEndian(WriteAt(extensions_offset - 4), |
| - kOneByteExtensionId); |
| - } |
| - |
| - WriteAt(extensions_offset + extensions_size_, |
| - (extension_id << 4) | (length - 1)); |
| - |
| - extension_entry->length = length; |
| - *offset = extensions_offset + kOneByteHeaderSize + extensions_size_; |
| - extension_entry->offset = *offset; |
| - extensions_size_ = new_extensions_size; |
| - |
| - // Update header length field. |
| - ByteWriter<uint16_t>::WriteBigEndian(WriteAt(extensions_offset - 2), |
| - extensions_words); |
| - // Fill extension padding place with zeroes. |
| - size_t extension_padding_size = 4 * extensions_words - extensions_size_; |
| - memset(WriteAt(extensions_offset + extensions_size_), 0, |
| - extension_padding_size); |
| - payload_offset_ = extensions_offset + 4 * extensions_words; |
| - buffer_.SetSize(payload_offset_); |
| - return true; |
| + // Extension not registered. |
| + return false; |
| } |
| uint8_t* Packet::WriteAt(size_t offset) { |