LCOV - code coverage report
Current view: top level - media/webrtc/trunk/webrtc/modules/rtp_rtcp/source - rtp_packet.cc (source / functions) Hit Total Coverage
Test: output.info Lines: 0 341 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 42 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13