xref: /aosp_15_r20/external/webrtc/modules/rtp_rtcp/source/rtp_packet.h (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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 #ifndef MODULES_RTP_RTCP_SOURCE_RTP_PACKET_H_
11 #define MODULES_RTP_RTCP_SOURCE_RTP_PACKET_H_
12 
13 #include <string>
14 #include <vector>
15 
16 #include "absl/types/optional.h"
17 #include "api/array_view.h"
18 #include "modules/rtp_rtcp/include/rtp_header_extension_map.h"
19 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
20 #include "rtc_base/copy_on_write_buffer.h"
21 
22 namespace webrtc {
23 
24 class RtpPacket {
25  public:
26   using ExtensionType = RTPExtensionType;
27   using ExtensionManager = RtpHeaderExtensionMap;
28 
29   // `extensions` required for SetExtension/ReserveExtension functions during
30   // packet creating and used if available in Parse function.
31   // Adding and getting extensions will fail until `extensions` is
32   // provided via constructor or IdentifyExtensions function.
33   // |*extensions| is only accessed during construction; the pointer is not
34   // stored.
35   RtpPacket();
36   explicit RtpPacket(const ExtensionManager* extensions);
37   RtpPacket(const RtpPacket&);
38   RtpPacket(const ExtensionManager* extensions, size_t capacity);
39   ~RtpPacket();
40 
41   RtpPacket& operator=(const RtpPacket&) = default;
42 
43   // Parse and copy given buffer into Packet.
44   // Does not require extension map to be registered (map is only required to
45   // read or allocate extensions in methods GetExtension, AllocateExtension,
46   // etc.)
47   bool Parse(const uint8_t* buffer, size_t size);
48   bool Parse(rtc::ArrayView<const uint8_t> packet);
49 
50   // Parse and move given buffer into Packet.
51   bool Parse(rtc::CopyOnWriteBuffer packet);
52 
53   // Maps extensions id to their types.
54   void IdentifyExtensions(ExtensionManager extensions);
55 
56   // Header.
Marker()57   bool Marker() const { return marker_; }
PayloadType()58   uint8_t PayloadType() const { return payload_type_; }
SequenceNumber()59   uint16_t SequenceNumber() const { return sequence_number_; }
Timestamp()60   uint32_t Timestamp() const { return timestamp_; }
Ssrc()61   uint32_t Ssrc() const { return ssrc_; }
62   std::vector<uint32_t> Csrcs() const;
63 
headers_size()64   size_t headers_size() const { return payload_offset_; }
65 
66   // Payload.
payload_size()67   size_t payload_size() const { return payload_size_; }
has_padding()68   bool has_padding() const { return buffer_[0] & 0x20; }
padding_size()69   size_t padding_size() const { return padding_size_; }
payload()70   rtc::ArrayView<const uint8_t> payload() const {
71     return rtc::MakeArrayView(data() + payload_offset_, payload_size_);
72   }
PayloadBuffer()73   rtc::CopyOnWriteBuffer PayloadBuffer() const {
74     return buffer_.Slice(payload_offset_, payload_size_);
75   }
76 
77   // Buffer.
Buffer()78   rtc::CopyOnWriteBuffer Buffer() const { return buffer_; }
capacity()79   size_t capacity() const { return buffer_.capacity(); }
size()80   size_t size() const {
81     return payload_offset_ + payload_size_ + padding_size_;
82   }
data()83   const uint8_t* data() const { return buffer_.cdata(); }
FreeCapacity()84   size_t FreeCapacity() const { return capacity() - size(); }
MaxPayloadSize()85   size_t MaxPayloadSize() const { return capacity() - headers_size(); }
86 
87   // Reset fields and buffer.
88   void Clear();
89 
90   // Header setters.
91   void CopyHeaderFrom(const RtpPacket& packet);
92   void SetMarker(bool marker_bit);
93   void SetPayloadType(uint8_t payload_type);
94   void SetSequenceNumber(uint16_t seq_no);
95   void SetTimestamp(uint32_t timestamp);
96   void SetSsrc(uint32_t ssrc);
97 
98   // Fills with zeroes mutable extensions,
99   // which are modified after FEC protection is generated.
100   void ZeroMutableExtensions();
101 
102   // Removes extension of given `type`, returns false is extension was not
103   // registered in packet's extension map or not present in the packet. Only
104   // extension that should be removed must be registered, other extensions may
105   // not be registered and will be preserved as is.
106   bool RemoveExtension(ExtensionType type);
107 
108   // Writes csrc list. Assumes:
109   // a) There is enough room left in buffer.
110   // b) Extension headers, payload or padding data has not already been added.
111   void SetCsrcs(rtc::ArrayView<const uint32_t> csrcs);
112 
113   // Header extensions.
114   template <typename Extension>
115   bool HasExtension() const;
116   bool HasExtension(ExtensionType type) const;
117 
118   // Returns whether there is an associated id for the extension and thus it is
119   // possible to set the extension.
120   template <typename Extension>
121   bool IsRegistered() const;
122 
123   template <typename Extension, typename FirstValue, typename... Values>
124   bool GetExtension(FirstValue, Values...) const;
125 
126   template <typename Extension>
127   absl::optional<typename Extension::value_type> GetExtension() const;
128 
129   // Returns view of the raw extension or empty view on failure.
130   template <typename Extension>
131   rtc::ArrayView<const uint8_t> GetRawExtension() const;
132 
133   template <typename Extension, typename... Values>
134   bool SetExtension(const Values&...);
135 
136   template <typename Extension>
137   bool ReserveExtension();
138 
139   // Find or allocate an extension `type`. Returns view of size `length`
140   // to write raw extension to or an empty view on failure.
141   rtc::ArrayView<uint8_t> AllocateExtension(ExtensionType type, size_t length);
142 
143   // Find an extension `type`.
144   // Returns view of the raw extension or empty view on failure.
145   rtc::ArrayView<const uint8_t> FindExtension(ExtensionType type) const;
146 
147   // Reserve size_bytes for payload. Returns nullptr on failure.
148   uint8_t* SetPayloadSize(size_t size_bytes);
149   // Same as SetPayloadSize but doesn't guarantee to keep current payload.
150   uint8_t* AllocatePayload(size_t size_bytes);
151 
152   bool SetPadding(size_t padding_size);
153 
154   // Returns debug string of RTP packet (without detailed extension info).
155   std::string ToString() const;
156 
157  private:
158   struct ExtensionInfo {
ExtensionInfoExtensionInfo159     explicit ExtensionInfo(uint8_t id) : ExtensionInfo(id, 0, 0) {}
ExtensionInfoExtensionInfo160     ExtensionInfo(uint8_t id, uint8_t length, uint16_t offset)
161         : id(id), length(length), offset(offset) {}
162     uint8_t id;
163     uint8_t length;
164     uint16_t offset;
165   };
166 
167   // Helper function for Parse. Fill header fields using data in given buffer,
168   // but does not touch packet own buffer, leaving packet in invalid state.
169   bool ParseBuffer(const uint8_t* buffer, size_t size);
170 
171   // Returns pointer to extension info for a given id. Returns nullptr if not
172   // found.
173   const ExtensionInfo* FindExtensionInfo(int id) const;
174 
175   // Returns reference to extension info for a given id. Creates a new entry
176   // with the specified id if not found.
177   ExtensionInfo& FindOrCreateExtensionInfo(int id);
178 
179   // Allocates and returns place to store rtp header extension.
180   // Returns empty arrayview on failure.
181   rtc::ArrayView<uint8_t> AllocateRawExtension(int id, size_t length);
182 
183   // Promotes existing one-byte header extensions to two-byte header extensions
184   // by rewriting the data and updates the corresponding extension offsets.
185   void PromoteToTwoByteHeaderExtension();
186 
187   uint16_t SetExtensionLengthMaybeAddZeroPadding(size_t extensions_offset);
188 
WriteAt(size_t offset)189   uint8_t* WriteAt(size_t offset) { return buffer_.MutableData() + offset; }
WriteAt(size_t offset,uint8_t byte)190   void WriteAt(size_t offset, uint8_t byte) {
191     buffer_.MutableData()[offset] = byte;
192   }
ReadAt(size_t offset)193   const uint8_t* ReadAt(size_t offset) const { return buffer_.data() + offset; }
194 
195   // Header.
196   bool marker_;
197   uint8_t payload_type_;
198   uint8_t padding_size_;
199   uint16_t sequence_number_;
200   uint32_t timestamp_;
201   uint32_t ssrc_;
202   size_t payload_offset_;  // Match header size with csrcs and extensions.
203   size_t payload_size_;
204 
205   ExtensionManager extensions_;
206   std::vector<ExtensionInfo> extension_entries_;
207   size_t extensions_size_ = 0;  // Unaligned.
208   rtc::CopyOnWriteBuffer buffer_;
209 };
210 
211 template <typename Extension>
HasExtension()212 bool RtpPacket::HasExtension() const {
213   return HasExtension(Extension::kId);
214 }
215 
216 template <typename Extension>
IsRegistered()217 bool RtpPacket::IsRegistered() const {
218   return extensions_.IsRegistered(Extension::kId);
219 }
220 
221 template <typename Extension, typename FirstValue, typename... Values>
GetExtension(FirstValue first,Values...values)222 bool RtpPacket::GetExtension(FirstValue first, Values... values) const {
223   auto raw = FindExtension(Extension::kId);
224   if (raw.empty())
225     return false;
226   return Extension::Parse(raw, first, values...);
227 }
228 
229 template <typename Extension>
GetExtension()230 absl::optional<typename Extension::value_type> RtpPacket::GetExtension() const {
231   absl::optional<typename Extension::value_type> result;
232   auto raw = FindExtension(Extension::kId);
233   if (raw.empty() || !Extension::Parse(raw, &result.emplace()))
234     result = absl::nullopt;
235   return result;
236 }
237 
238 template <typename Extension>
GetRawExtension()239 rtc::ArrayView<const uint8_t> RtpPacket::GetRawExtension() const {
240   return FindExtension(Extension::kId);
241 }
242 
243 template <typename Extension, typename... Values>
SetExtension(const Values &...values)244 bool RtpPacket::SetExtension(const Values&... values) {
245   const size_t value_size = Extension::ValueSize(values...);
246   auto buffer = AllocateExtension(Extension::kId, value_size);
247   if (buffer.empty())
248     return false;
249   return Extension::Write(buffer, values...);
250 }
251 
252 template <typename Extension>
ReserveExtension()253 bool RtpPacket::ReserveExtension() {
254   auto buffer = AllocateExtension(Extension::kId, Extension::kValueSizeBytes);
255   if (buffer.empty())
256     return false;
257   memset(buffer.data(), 0, Extension::kValueSizeBytes);
258   return true;
259 }
260 
261 }  // namespace webrtc
262 
263 #endif  // MODULES_RTP_RTCP_SOURCE_RTP_PACKET_H_
264