tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

rtp_packet.cc (27153B)


      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 "modules/rtp_rtcp/source/rtp_packet.h"
     12 
     13 #include <cstdint>
     14 #include <cstring>
     15 #include <string>
     16 #include <utility>
     17 #include <vector>
     18 
     19 #include "api/array_view.h"
     20 #include "api/rtp_parameters.h"
     21 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
     22 #include "modules/rtp_rtcp/source/byte_io.h"
     23 #include "modules/rtp_rtcp/source/rtp_header_extensions.h"
     24 #include "rtc_base/checks.h"
     25 #include "rtc_base/copy_on_write_buffer.h"
     26 #include "rtc_base/logging.h"
     27 #include "rtc_base/numerics/safe_conversions.h"
     28 #include "rtc_base/strings/string_builder.h"
     29 
     30 namespace webrtc {
     31 namespace {
     32 constexpr size_t kFixedHeaderSize = 12;
     33 constexpr uint8_t kRtpVersion = 2;
     34 constexpr uint16_t kOneByteExtensionProfileId = 0xBEDE;
     35 constexpr uint16_t kTwoByteExtensionProfileId = 0x1000;
     36 constexpr uint16_t kTwobyteExtensionProfileIdAppBitsFilter = 0xfff0;
     37 constexpr size_t kOneByteExtensionHeaderLength = 1;
     38 constexpr size_t kTwoByteExtensionHeaderLength = 2;
     39 constexpr size_t kDefaultPacketSize = 1500;
     40 }  // namespace
     41 
     42 //  0                   1                   2                   3
     43 //  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
     44 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     45 // |V=2|P|X|  CC   |M|     PT      |       sequence number         |
     46 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     47 // |                           timestamp                           |
     48 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     49 // |           synchronization source (SSRC) identifier            |
     50 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
     51 // |            Contributing source (CSRC) identifiers             |
     52 // |                             ....                              |
     53 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
     54 // |  header eXtension profile id  |       length in 32bits        |
     55 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     56 // |                          Extensions                           |
     57 // |                             ....                              |
     58 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
     59 // |                           Payload                             |
     60 // |             ....              :  padding...                   |
     61 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     62 // |               padding         | Padding size  |
     63 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     64 RtpPacket::RtpPacket() : RtpPacket(nullptr, kDefaultPacketSize) {}
     65 
     66 RtpPacket::RtpPacket(const ExtensionManager* extensions)
     67    : RtpPacket(extensions, kDefaultPacketSize) {}
     68 
     69 RtpPacket::RtpPacket(const ExtensionManager* extensions, size_t capacity)
     70    : extensions_(extensions ? *extensions : ExtensionManager()),
     71      buffer_(capacity) {
     72  RTC_DCHECK_GE(capacity, kFixedHeaderSize);
     73  Clear();
     74 }
     75 
     76 RtpPacket::RtpPacket(const RtpPacket&) = default;
     77 RtpPacket::RtpPacket(RtpPacket&&) = default;
     78 RtpPacket& RtpPacket::operator=(const RtpPacket&) = default;
     79 RtpPacket& RtpPacket::operator=(RtpPacket&&) = default;
     80 RtpPacket::~RtpPacket() = default;
     81 
     82 void RtpPacket::IdentifyExtensions(ExtensionManager extensions) {
     83  extensions_ = std::move(extensions);
     84 }
     85 
     86 bool RtpPacket::Parse(const uint8_t* buffer, size_t buffer_size) {
     87  if (!ParseBuffer(buffer, buffer_size)) {
     88    Clear();
     89    return false;
     90  }
     91  buffer_.SetData(buffer, buffer_size);
     92  RTC_DCHECK_EQ(size(), buffer_size);
     93  return true;
     94 }
     95 
     96 bool RtpPacket::Parse(ArrayView<const uint8_t> packet) {
     97  return Parse(packet.data(), packet.size());
     98 }
     99 
    100 bool RtpPacket::Parse(CopyOnWriteBuffer buffer) {
    101  if (!ParseBuffer(buffer.cdata(), buffer.size())) {
    102    Clear();
    103    return false;
    104  }
    105  size_t buffer_size = buffer.size();
    106  buffer_ = std::move(buffer);
    107  RTC_DCHECK_EQ(size(), buffer_size);
    108  return true;
    109 }
    110 
    111 std::vector<uint32_t> RtpPacket::Csrcs() const {
    112  size_t num_csrc = data()[0] & 0x0F;
    113  RTC_DCHECK_GE(capacity(), kFixedHeaderSize + num_csrc * 4);
    114  std::vector<uint32_t> csrcs(num_csrc);
    115  for (size_t i = 0; i < num_csrc; ++i) {
    116    csrcs[i] =
    117        ByteReader<uint32_t>::ReadBigEndian(&data()[kFixedHeaderSize + i * 4]);
    118  }
    119  return csrcs;
    120 }
    121 
    122 void RtpPacket::CopyHeaderFrom(const RtpPacket& packet) {
    123  marker_ = packet.marker_;
    124  payload_type_ = packet.payload_type_;
    125  sequence_number_ = packet.sequence_number_;
    126  timestamp_ = packet.timestamp_;
    127  ssrc_ = packet.ssrc_;
    128  payload_offset_ = packet.payload_offset_;
    129  extensions_ = packet.extensions_;
    130  extension_entries_ = packet.extension_entries_;
    131  extensions_size_ = packet.extensions_size_;
    132  buffer_ = packet.buffer_.Slice(0, packet.headers_size());
    133  // Reset payload and padding.
    134  payload_size_ = 0;
    135  padding_size_ = 0;
    136 }
    137 
    138 void RtpPacket::SetMarker(bool marker_bit) {
    139  marker_ = marker_bit;
    140  if (marker_) {
    141    WriteAt(1, data()[1] | 0x80);
    142  } else {
    143    WriteAt(1, data()[1] & 0x7F);
    144  }
    145 }
    146 
    147 void RtpPacket::SetPayloadType(uint8_t payload_type) {
    148  RTC_DCHECK_LE(payload_type, 0x7Fu);
    149  payload_type_ = payload_type;
    150  WriteAt(1, (data()[1] & 0x80) | payload_type);
    151 }
    152 
    153 void RtpPacket::SetSequenceNumber(uint16_t seq_no) {
    154  sequence_number_ = seq_no;
    155  ByteWriter<uint16_t>::WriteBigEndian(WriteAt(2), seq_no);
    156 }
    157 
    158 void RtpPacket::SetTimestamp(uint32_t timestamp) {
    159  timestamp_ = timestamp;
    160  ByteWriter<uint32_t>::WriteBigEndian(WriteAt(4), timestamp);
    161 }
    162 
    163 void RtpPacket::SetSsrc(uint32_t ssrc) {
    164  ssrc_ = ssrc;
    165  ByteWriter<uint32_t>::WriteBigEndian(WriteAt(8), ssrc);
    166 }
    167 
    168 void RtpPacket::ZeroMutableExtensions() {
    169  for (const ExtensionInfo& extension : extension_entries_) {
    170    switch (extensions_.GetType(extension.id)) {
    171      case RTPExtensionType::kRtpExtensionNone: {
    172        RTC_LOG(LS_WARNING) << "Unidentified extension in the packet.";
    173        break;
    174      }
    175      case RTPExtensionType::kRtpExtensionVideoTiming: {
    176        // Nullify last entries, starting at pacer delay.
    177        // These are set by pacer and SFUs
    178        if (VideoTimingExtension::kPacerExitDeltaOffset < extension.length) {
    179          memset(
    180              WriteAt(extension.offset +
    181                      VideoTimingExtension::kPacerExitDeltaOffset),
    182              0,
    183              extension.length - VideoTimingExtension::kPacerExitDeltaOffset);
    184        }
    185        break;
    186      }
    187      case RTPExtensionType::kRtpExtensionTransportSequenceNumber:
    188      case RTPExtensionType::kRtpExtensionTransportSequenceNumber02:
    189      case RTPExtensionType::kRtpExtensionTransmissionTimeOffset:
    190      case RTPExtensionType::kRtpExtensionAbsoluteSendTime: {
    191        // Nullify whole extension, as it's filled in the pacer.
    192        memset(WriteAt(extension.offset), 0, extension.length);
    193        break;
    194      }
    195      case RTPExtensionType::kRtpExtensionAudioLevel:
    196 #if !defined(WEBRTC_MOZILLA_BUILD)
    197      case RTPExtensionType::kRtpExtensionCsrcAudioLevel:
    198 #endif
    199      case RTPExtensionType::kRtpExtensionAbsoluteCaptureTime:
    200      case RTPExtensionType::kRtpExtensionColorSpace:
    201      case RTPExtensionType::kRtpExtensionCorruptionDetection:
    202      case RTPExtensionType::kRtpExtensionGenericFrameDescriptor:
    203      case RTPExtensionType::kRtpExtensionDependencyDescriptor:
    204      case RTPExtensionType::kRtpExtensionMid:
    205      case RTPExtensionType::kRtpExtensionNumberOfExtensions:
    206      case RTPExtensionType::kRtpExtensionPlayoutDelay:
    207      case RTPExtensionType::kRtpExtensionRepairedRtpStreamId:
    208      case RTPExtensionType::kRtpExtensionRtpStreamId:
    209      case RTPExtensionType::kRtpExtensionVideoContentType:
    210      case RTPExtensionType::kRtpExtensionVideoLayersAllocation:
    211      case RTPExtensionType::kRtpExtensionVideoRotation:
    212      case RTPExtensionType::kRtpExtensionInbandComfortNoise:
    213      case RTPExtensionType::kRtpExtensionVideoFrameTrackingId: {
    214        // Non-mutable extension. Don't change it.
    215        break;
    216      }
    217 #if defined(WEBRTC_MOZILLA_BUILD)
    218      case RTPExtensionType::kRtpExtensionCsrcAudioLevel: {
    219        // TODO: This is a Mozilla addition, we need to add a handler for this.
    220        RTC_CHECK(false);
    221      }
    222 #endif
    223    }
    224  }
    225 }
    226 
    227 void RtpPacket::SetCsrcs(ArrayView<const uint32_t> csrcs) {
    228  RTC_DCHECK_EQ(extensions_size_, 0);
    229  RTC_DCHECK_EQ(payload_size_, 0);
    230  RTC_DCHECK_EQ(padding_size_, 0);
    231  RTC_DCHECK_LE(csrcs.size(), 0x0fu);
    232  RTC_DCHECK_LE(kFixedHeaderSize + 4 * csrcs.size(), capacity());
    233  payload_offset_ = kFixedHeaderSize + 4 * csrcs.size();
    234  WriteAt(0, (data()[0] & 0xF0) | dchecked_cast<uint8_t>(csrcs.size()));
    235  size_t offset = kFixedHeaderSize;
    236  for (uint32_t csrc : csrcs) {
    237    ByteWriter<uint32_t>::WriteBigEndian(WriteAt(offset), csrc);
    238    offset += 4;
    239  }
    240  buffer_.SetSize(payload_offset_);
    241 }
    242 
    243 ArrayView<uint8_t> RtpPacket::AllocateRawExtension(int id, size_t length) {
    244  RTC_DCHECK_GE(id, RtpExtension::kMinId);
    245  RTC_DCHECK_LE(id, RtpExtension::kMaxId);
    246  RTC_DCHECK_GE(length, 1);
    247  RTC_DCHECK_LE(length, RtpExtension::kMaxValueSize);
    248  const ExtensionInfo* extension_entry = FindExtensionInfo(id);
    249  if (extension_entry != nullptr) {
    250    // Extension already reserved. Check if same length is used.
    251    if (extension_entry->length == length)
    252      return MakeArrayView(WriteAt(extension_entry->offset), length);
    253 
    254    RTC_LOG(LS_ERROR) << "Length mismatch for extension id " << id
    255                      << ": expected "
    256                      << static_cast<int>(extension_entry->length)
    257                      << ". received " << length;
    258    return nullptr;
    259  }
    260  if (payload_size_ > 0) {
    261    RTC_LOG(LS_ERROR) << "Can't add new extension id " << id
    262                      << " after payload was set.";
    263    return nullptr;
    264  }
    265  if (padding_size_ > 0) {
    266    RTC_LOG(LS_ERROR) << "Can't add new extension id " << id
    267                      << " after padding was set.";
    268    return nullptr;
    269  }
    270 
    271  const size_t num_csrc = data()[0] & 0x0F;
    272  const size_t extensions_offset = kFixedHeaderSize + (num_csrc * 4) + 4;
    273  // Determine if two-byte header is required for the extension based on id and
    274  // length. Please note that a length of 0 also requires two-byte header
    275  // extension. See RFC8285 Section 4.2-4.3.
    276  const bool two_byte_header_required =
    277      id > RtpExtension::kOneByteHeaderExtensionMaxId ||
    278      length > RtpExtension::kOneByteHeaderExtensionMaxValueSize || length == 0;
    279  RTC_CHECK(!two_byte_header_required || extensions_.ExtmapAllowMixed());
    280 
    281  uint16_t profile_id;
    282  if (extensions_size_ > 0) {
    283    profile_id =
    284        ByteReader<uint16_t>::ReadBigEndian(data() + extensions_offset - 4);
    285    if (profile_id == kOneByteExtensionProfileId && two_byte_header_required) {
    286      // Is buffer size big enough to fit promotion and new data field?
    287      // The header extension will grow with one byte per already allocated
    288      // extension + the size of the extension that is about to be allocated.
    289      size_t expected_new_extensions_size =
    290          extensions_size_ + extension_entries_.size() +
    291          kTwoByteExtensionHeaderLength + length;
    292      if (extensions_offset + expected_new_extensions_size > capacity()) {
    293        RTC_LOG(LS_ERROR)
    294            << "Extension cannot be registered: Not enough space left in "
    295               "buffer to change to two-byte header extension and add new "
    296               "extension.";
    297        return nullptr;
    298      }
    299      // Promote already written data to two-byte header format.
    300      PromoteToTwoByteHeaderExtension();
    301      profile_id = kTwoByteExtensionProfileId;
    302    }
    303  } else {
    304    // Profile specific ID, set to OneByteExtensionHeader unless
    305    // TwoByteExtensionHeader is required.
    306    profile_id = two_byte_header_required ? kTwoByteExtensionProfileId
    307                                          : kOneByteExtensionProfileId;
    308  }
    309 
    310  const size_t extension_header_size = profile_id == kOneByteExtensionProfileId
    311                                           ? kOneByteExtensionHeaderLength
    312                                           : kTwoByteExtensionHeaderLength;
    313  size_t new_extensions_size =
    314      extensions_size_ + extension_header_size + length;
    315  if (extensions_offset + new_extensions_size > capacity()) {
    316    RTC_LOG(LS_ERROR)
    317        << "Extension cannot be registered: Not enough space left in buffer.";
    318    return nullptr;
    319  }
    320 
    321  // All checks passed, write down the extension headers.
    322  if (extensions_size_ == 0) {
    323    RTC_DCHECK_EQ(payload_offset_, kFixedHeaderSize + (num_csrc * 4));
    324    WriteAt(0, data()[0] | 0x10);  // Set extension bit.
    325    ByteWriter<uint16_t>::WriteBigEndian(WriteAt(extensions_offset - 4),
    326                                         profile_id);
    327  }
    328 
    329  if (profile_id == kOneByteExtensionProfileId) {
    330    uint8_t one_byte_header = dchecked_cast<uint8_t>(id) << 4;
    331    one_byte_header |= dchecked_cast<uint8_t>(length - 1);
    332    WriteAt(extensions_offset + extensions_size_, one_byte_header);
    333  } else {
    334    // TwoByteHeaderExtension.
    335    uint8_t extension_id = dchecked_cast<uint8_t>(id);
    336    WriteAt(extensions_offset + extensions_size_, extension_id);
    337    uint8_t extension_length = dchecked_cast<uint8_t>(length);
    338    WriteAt(extensions_offset + extensions_size_ + 1, extension_length);
    339  }
    340 
    341  const uint16_t extension_info_offset = dchecked_cast<uint16_t>(
    342      extensions_offset + extensions_size_ + extension_header_size);
    343  const uint8_t extension_info_length = dchecked_cast<uint8_t>(length);
    344  extension_entries_.emplace_back(id, extension_info_length,
    345                                  extension_info_offset);
    346 
    347  extensions_size_ = new_extensions_size;
    348 
    349  uint16_t extensions_size_padded =
    350      SetExtensionLengthMaybeAddZeroPadding(extensions_offset);
    351  payload_offset_ = extensions_offset + extensions_size_padded;
    352  buffer_.SetSize(payload_offset_);
    353  return MakeArrayView(WriteAt(extension_info_offset), extension_info_length);
    354 }
    355 
    356 void RtpPacket::PromoteToTwoByteHeaderExtension() {
    357  size_t num_csrc = data()[0] & 0x0F;
    358  size_t extensions_offset = kFixedHeaderSize + (num_csrc * 4) + 4;
    359 
    360  RTC_CHECK_GT(extension_entries_.size(), 0);
    361  RTC_CHECK_EQ(payload_size_, 0);
    362  RTC_CHECK_EQ(kOneByteExtensionProfileId, ByteReader<uint16_t>::ReadBigEndian(
    363                                               data() + extensions_offset - 4));
    364  // Rewrite data.
    365  // Each extension adds one to the offset. The write-read delta for the last
    366  // extension is therefore the same as the number of extension entries.
    367  size_t write_read_delta = extension_entries_.size();
    368  for (auto extension_entry = extension_entries_.rbegin();
    369       extension_entry != extension_entries_.rend(); ++extension_entry) {
    370    size_t read_index = extension_entry->offset;
    371    size_t write_index = read_index + write_read_delta;
    372    // Update offset.
    373    extension_entry->offset = dchecked_cast<uint16_t>(write_index);
    374    // Copy data. Use memmove since read/write regions may overlap.
    375    memmove(WriteAt(write_index), data() + read_index, extension_entry->length);
    376    // Rewrite id and length.
    377    WriteAt(--write_index, extension_entry->length);
    378    WriteAt(--write_index, extension_entry->id);
    379    --write_read_delta;
    380  }
    381 
    382  // Update profile header, extensions length, and zero padding.
    383  ByteWriter<uint16_t>::WriteBigEndian(WriteAt(extensions_offset - 4),
    384                                       kTwoByteExtensionProfileId);
    385  extensions_size_ += extension_entries_.size();
    386  uint16_t extensions_size_padded =
    387      SetExtensionLengthMaybeAddZeroPadding(extensions_offset);
    388  payload_offset_ = extensions_offset + extensions_size_padded;
    389  buffer_.SetSize(payload_offset_);
    390 }
    391 
    392 uint16_t RtpPacket::SetExtensionLengthMaybeAddZeroPadding(
    393    size_t extensions_offset) {
    394  // Update header length field.
    395  uint16_t extensions_words =
    396      dchecked_cast<uint16_t>((extensions_size_ + 3) / 4);  // Wrap up to 32bit.
    397  ByteWriter<uint16_t>::WriteBigEndian(WriteAt(extensions_offset - 2),
    398                                       extensions_words);
    399  // Fill extension padding place with zeroes.
    400  size_t extension_padding_size = 4 * extensions_words - extensions_size_;
    401  memset(WriteAt(extensions_offset + extensions_size_), 0,
    402         extension_padding_size);
    403  return 4 * extensions_words;
    404 }
    405 
    406 uint8_t* RtpPacket::AllocatePayload(size_t size_bytes) {
    407  // Reset payload size to 0. If CopyOnWrite buffer_ was shared, this will cause
    408  // reallocation and memcpy. Keeping just header reduces memcpy size.
    409  SetPayloadSize(0);
    410  return SetPayloadSize(size_bytes);
    411 }
    412 
    413 void RtpPacket::SetPayload(ArrayView<const uint8_t> payload) {
    414  memcpy(AllocatePayload(payload.size()), payload.data(), payload.size());
    415 }
    416 
    417 uint8_t* RtpPacket::SetPayloadSize(size_t size_bytes) {
    418  RTC_DCHECK_EQ(padding_size_, 0);
    419  payload_size_ = size_bytes;
    420  buffer_.SetSize(payload_offset_ + payload_size_);
    421  return WriteAt(payload_offset_);
    422 }
    423 
    424 bool RtpPacket::SetPadding(size_t padding_bytes) {
    425  if (payload_offset_ + payload_size_ + padding_bytes > capacity()) {
    426    RTC_LOG(LS_WARNING) << "Cannot set padding size " << padding_bytes
    427                        << ", only "
    428                        << (capacity() - payload_offset_ - payload_size_)
    429                        << " bytes left in buffer.";
    430    return false;
    431  }
    432  padding_size_ = dchecked_cast<uint8_t>(padding_bytes);
    433  buffer_.SetSize(payload_offset_ + payload_size_ + padding_size_);
    434  if (padding_size_ > 0) {
    435    size_t padding_offset = payload_offset_ + payload_size_;
    436    size_t padding_end = padding_offset + padding_size_;
    437    memset(WriteAt(padding_offset), 0, padding_size_ - 1);
    438    WriteAt(padding_end - 1, padding_size_);
    439    WriteAt(0, data()[0] | 0x20);  // Set padding bit.
    440  } else {
    441    WriteAt(0, data()[0] & ~0x20);  // Clear padding bit.
    442  }
    443  return true;
    444 }
    445 
    446 void RtpPacket::Clear() {
    447  marker_ = false;
    448  payload_type_ = 0;
    449  sequence_number_ = 0;
    450  timestamp_ = 0;
    451  ssrc_ = 0;
    452  payload_offset_ = kFixedHeaderSize;
    453  payload_size_ = 0;
    454  padding_size_ = 0;
    455  extensions_size_ = 0;
    456  extension_entries_.clear();
    457 
    458  memset(WriteAt(0), 0, kFixedHeaderSize);
    459  buffer_.SetSize(kFixedHeaderSize);
    460  WriteAt(0, kRtpVersion << 6);
    461 }
    462 
    463 bool RtpPacket::ParseBuffer(const uint8_t* buffer, size_t size) {
    464  if (size < kFixedHeaderSize) {
    465    return false;
    466  }
    467  const uint8_t version = buffer[0] >> 6;
    468  if (version != kRtpVersion) {
    469    return false;
    470  }
    471  const bool has_padding = (buffer[0] & 0x20) != 0;
    472  const bool has_extension = (buffer[0] & 0x10) != 0;
    473  const uint8_t number_of_crcs = buffer[0] & 0x0f;
    474  marker_ = (buffer[1] & 0x80) != 0;
    475  payload_type_ = buffer[1] & 0x7f;
    476 
    477  sequence_number_ = ByteReader<uint16_t>::ReadBigEndian(&buffer[2]);
    478  timestamp_ = ByteReader<uint32_t>::ReadBigEndian(&buffer[4]);
    479  ssrc_ = ByteReader<uint32_t>::ReadBigEndian(&buffer[8]);
    480  if (size < kFixedHeaderSize + number_of_crcs * 4) {
    481    return false;
    482  }
    483  payload_offset_ = kFixedHeaderSize + number_of_crcs * 4;
    484 
    485  extensions_size_ = 0;
    486  extension_entries_.clear();
    487  if (has_extension) {
    488    /* RTP header extension, RFC 3550.
    489     0                   1                   2                   3
    490     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
    491    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    492    |      defined by profile       |           length              |
    493    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    494    |                        header extension                       |
    495    |                             ....                              |
    496    */
    497    size_t extension_offset = payload_offset_ + 4;
    498    if (extension_offset > size) {
    499      return false;
    500    }
    501    uint16_t profile =
    502        ByteReader<uint16_t>::ReadBigEndian(&buffer[payload_offset_]);
    503    size_t extensions_capacity =
    504        ByteReader<uint16_t>::ReadBigEndian(&buffer[payload_offset_ + 2]);
    505    extensions_capacity *= 4;
    506    if (extension_offset + extensions_capacity > size) {
    507      return false;
    508    }
    509    if (profile != kOneByteExtensionProfileId &&
    510        (profile & kTwobyteExtensionProfileIdAppBitsFilter) !=
    511            kTwoByteExtensionProfileId) {
    512      RTC_LOG(LS_WARNING) << "Unsupported rtp extension " << profile;
    513    } else {
    514      size_t extension_header_length = profile == kOneByteExtensionProfileId
    515                                           ? kOneByteExtensionHeaderLength
    516                                           : kTwoByteExtensionHeaderLength;
    517      constexpr uint8_t kPaddingByte = 0;
    518      constexpr uint8_t kPaddingId = 0;
    519      constexpr uint8_t kOneByteHeaderExtensionReservedId = 15;
    520      while (extensions_size_ + extension_header_length < extensions_capacity) {
    521        if (buffer[extension_offset + extensions_size_] == kPaddingByte) {
    522          extensions_size_++;
    523          continue;
    524        }
    525        int id;
    526        uint8_t length;
    527        if (profile == kOneByteExtensionProfileId) {
    528          id = buffer[extension_offset + extensions_size_] >> 4;
    529          length = 1 + (buffer[extension_offset + extensions_size_] & 0xf);
    530          if (id == kOneByteHeaderExtensionReservedId ||
    531              (id == kPaddingId && length != 1)) {
    532            break;
    533          }
    534        } else {
    535          id = buffer[extension_offset + extensions_size_];
    536          length = buffer[extension_offset + extensions_size_ + 1];
    537        }
    538 
    539        if (extensions_size_ + extension_header_length + length >
    540            extensions_capacity) {
    541          RTC_LOG(LS_WARNING) << "Oversized rtp header extension.";
    542          break;
    543        }
    544 
    545        ExtensionInfo& extension_info = FindOrCreateExtensionInfo(id);
    546        if (extension_info.length != 0) {
    547          RTC_LOG(LS_VERBOSE)
    548              << "Duplicate rtp header extension id " << id << ". Overwriting.";
    549        }
    550 
    551        size_t offset =
    552            extension_offset + extensions_size_ + extension_header_length;
    553        if (!IsValueInRangeForNumericType<uint16_t>(offset)) {
    554          RTC_DLOG(LS_WARNING) << "Oversized rtp header extension.";
    555          break;
    556        }
    557        extension_info.offset = static_cast<uint16_t>(offset);
    558        extension_info.length = length;
    559        extensions_size_ += extension_header_length + length;
    560      }
    561    }
    562    payload_offset_ = extension_offset + extensions_capacity;
    563  }
    564 
    565  if (has_padding && payload_offset_ < size) {
    566    padding_size_ = buffer[size - 1];
    567    if (padding_size_ == 0) {
    568      RTC_LOG(LS_WARNING) << "Padding was set, but padding size is zero";
    569      return false;
    570    }
    571  } else {
    572    padding_size_ = 0;
    573  }
    574 
    575  if (payload_offset_ + padding_size_ > size) {
    576    return false;
    577  }
    578  payload_size_ = size - payload_offset_ - padding_size_;
    579  return true;
    580 }
    581 
    582 const RtpPacket::ExtensionInfo* RtpPacket::FindExtensionInfo(int id) const {
    583  for (const ExtensionInfo& extension : extension_entries_) {
    584    if (extension.id == id) {
    585      return &extension;
    586    }
    587  }
    588  return nullptr;
    589 }
    590 
    591 RtpPacket::ExtensionInfo& RtpPacket::FindOrCreateExtensionInfo(int id) {
    592  for (ExtensionInfo& extension : extension_entries_) {
    593    if (extension.id == id) {
    594      return extension;
    595    }
    596  }
    597  extension_entries_.emplace_back(id);
    598  return extension_entries_.back();
    599 }
    600 
    601 ArrayView<const uint8_t> RtpPacket::FindExtension(ExtensionType type) const {
    602  uint8_t id = extensions_.GetId(type);
    603  if (id == ExtensionManager::kInvalidId) {
    604    // Extension not registered.
    605    return nullptr;
    606  }
    607  ExtensionInfo const* extension_info = FindExtensionInfo(id);
    608  if (extension_info == nullptr) {
    609    return nullptr;
    610  }
    611  return MakeArrayView(data() + extension_info->offset, extension_info->length);
    612 }
    613 
    614 ArrayView<uint8_t> RtpPacket::AllocateExtension(ExtensionType type,
    615                                                size_t length) {
    616  // TODO(webrtc:7990): Add support for empty extensions (length==0).
    617  if (length == 0 || length > RtpExtension::kMaxValueSize ||
    618      (!extensions_.ExtmapAllowMixed() &&
    619       length > RtpExtension::kOneByteHeaderExtensionMaxValueSize)) {
    620    return nullptr;
    621  }
    622 
    623  uint8_t id = extensions_.GetId(type);
    624  if (id == ExtensionManager::kInvalidId) {
    625    // Extension not registered.
    626    return nullptr;
    627  }
    628  if (!extensions_.ExtmapAllowMixed() &&
    629      id > RtpExtension::kOneByteHeaderExtensionMaxId) {
    630    return nullptr;
    631  }
    632  return AllocateRawExtension(id, length);
    633 }
    634 
    635 bool RtpPacket::HasExtension(ExtensionType type) const {
    636  uint8_t id = extensions_.GetId(type);
    637  if (id == ExtensionManager::kInvalidId) {
    638    // Extension not registered.
    639    return false;
    640  }
    641  return FindExtensionInfo(id) != nullptr;
    642 }
    643 
    644 bool RtpPacket::RemoveExtension(ExtensionType type) {
    645  uint8_t id_to_remove = extensions_.GetId(type);
    646  if (id_to_remove == ExtensionManager::kInvalidId) {
    647    // Extension not registered.
    648    RTC_LOG(LS_ERROR) << "Extension not registered, type=" << type
    649                      << ", packet=" << ToString();
    650    return false;
    651  }
    652 
    653  // Rebuild new packet from scratch.
    654  RtpPacket new_packet;
    655 
    656  new_packet.SetMarker(Marker());
    657  new_packet.SetPayloadType(PayloadType());
    658  new_packet.SetSequenceNumber(SequenceNumber());
    659  new_packet.SetTimestamp(Timestamp());
    660  new_packet.SetSsrc(Ssrc());
    661  new_packet.IdentifyExtensions(extensions_);
    662 
    663  // Copy all extensions, except the one we are removing.
    664  bool found_extension = false;
    665  for (const ExtensionInfo& ext : extension_entries_) {
    666    if (ext.id == id_to_remove) {
    667      found_extension = true;
    668    } else {
    669      auto extension_data = new_packet.AllocateRawExtension(ext.id, ext.length);
    670      if (extension_data.size() != ext.length) {
    671        RTC_LOG(LS_ERROR) << "Failed to allocate extension id=" << ext.id
    672                          << ", length=" << ext.length
    673                          << ", packet=" << ToString();
    674        return false;
    675      }
    676 
    677      // Copy extension data to new packet.
    678      memcpy(extension_data.data(), ReadAt(ext.offset), ext.length);
    679    }
    680  }
    681 
    682  if (!found_extension) {
    683    RTC_LOG(LS_WARNING) << "Extension not present in RTP packet, type=" << type
    684                        << ", packet=" << ToString();
    685    return false;
    686  }
    687 
    688  // Copy payload data to new packet.
    689  if (payload_size() > 0) {
    690    memcpy(new_packet.AllocatePayload(payload_size()), payload().data(),
    691           payload_size());
    692  } else {
    693    new_packet.SetPayloadSize(0);
    694  }
    695 
    696  // Allocate padding -- must be last!
    697  new_packet.SetPadding(padding_size());
    698 
    699  // Success, replace current packet with newly built packet.
    700  *this = new_packet;
    701  return true;
    702 }
    703 
    704 std::string RtpPacket::ToString() const {
    705  StringBuilder result;
    706  result << "{payload_type=" << payload_type_ << ", marker=" << marker_
    707         << ", sequence_number=" << sequence_number_
    708         << ", padding_size=" << padding_size_ << ", timestamp=" << timestamp_
    709         << ", ssrc=" << ssrc_ << ", payload_offset=" << payload_offset_
    710         << ", payload_size=" << payload_size_ << ", total_size=" << size()
    711         << "}";
    712 
    713  return result.Release();
    714 }
    715 
    716 }  // namespace webrtc