blob: e2e291cf5da225e59296238b06ed2eafd0bb5e14 [file] [log] [blame]
danilchap1edb7ab2016-04-20 05:25:10 -07001/*
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 */
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020010#ifndef MODULES_RTP_RTCP_SOURCE_RTP_PACKET_H_
11#define MODULES_RTP_RTCP_SOURCE_RTP_PACKET_H_
danilchap1edb7ab2016-04-20 05:25:10 -070012
Anton Sukhanovff25b872019-07-09 13:04:07 -070013#include <string>
danilchap1edb7ab2016-04-20 05:25:10 -070014#include <vector>
15
Danil Chapovalovc5dd3002018-11-08 15:12:45 +010016#include "absl/types/optional.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020017#include "api/array_view.h"
Johannes Kronc5744b82018-09-24 14:50:48 +020018#include "modules/rtp_rtcp/include/rtp_header_extension_map.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020019#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
Steve Anton10542f22019-01-11 09:11:00 -080020#include "rtc_base/copy_on_write_buffer.h"
danilchap1edb7ab2016-04-20 05:25:10 -070021
22namespace webrtc {
danilchap1edb7ab2016-04-20 05:25:10 -070023
Danil Chapovalov8769e172017-09-14 14:08:22 +020024class RtpPacket {
danilchap1edb7ab2016-04-20 05:25:10 -070025 public:
26 using ExtensionType = RTPExtensionType;
27 using ExtensionManager = RtpHeaderExtensionMap;
danilchap1edb7ab2016-04-20 05:25:10 -070028
eladalon87443ee2017-09-13 02:45:15 -070029 // |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.
Henrik Grunellc463a782020-12-22 14:47:07 +010033 // |*extensions| is only accessed during construction; the pointer is not
34 // stored.
Danil Chapovalov8769e172017-09-14 14:08:22 +020035 RtpPacket();
36 explicit RtpPacket(const ExtensionManager* extensions);
37 RtpPacket(const RtpPacket&);
38 RtpPacket(const ExtensionManager* extensions, size_t capacity);
39 ~RtpPacket();
eladalon87443ee2017-09-13 02:45:15 -070040
Danil Chapovalov8769e172017-09-14 14:08:22 +020041 RtpPacket& operator=(const RtpPacket&) = default;
eladalon87443ee2017-09-13 02:45:15 -070042
danilchap1edb7ab2016-04-20 05:25:10 -070043 // Parse and copy given buffer into Packet.
Anton Sukhanovff25b872019-07-09 13:04:07 -070044 // Does not require extension map to be registered (map is only required to
45 // read or allocate extensions in methods GetExtension, AllocateExtension,
46 // etc.)
danilchap1edb7ab2016-04-20 05:25:10 -070047 bool Parse(const uint8_t* buffer, size_t size);
brandtrb29e6522016-12-21 06:37:18 -080048 bool Parse(rtc::ArrayView<const uint8_t> packet);
danilchap1edb7ab2016-04-20 05:25:10 -070049
50 // Parse and move given buffer into Packet.
Danil Chapovalov31e4e802016-08-03 18:27:40 +020051 bool Parse(rtc::CopyOnWriteBuffer packet);
danilchap1edb7ab2016-04-20 05:25:10 -070052
danilchap70f39a32016-12-16 05:48:18 -080053 // Maps extensions id to their types.
Tommid3500062021-06-14 19:39:45 +020054 void IdentifyExtensions(ExtensionManager extensions);
danilchap1edb7ab2016-04-20 05:25:10 -070055
56 // Header.
Danil Chapovalov7d2df3f2018-08-14 17:18:07 +020057 bool Marker() const { return marker_; }
58 uint8_t PayloadType() const { return payload_type_; }
59 uint16_t SequenceNumber() const { return sequence_number_; }
60 uint32_t Timestamp() const { return timestamp_; }
61 uint32_t Ssrc() const { return ssrc_; }
danilchap1edb7ab2016-04-20 05:25:10 -070062 std::vector<uint32_t> Csrcs() const;
63
Danil Chapovalov7d2df3f2018-08-14 17:18:07 +020064 size_t headers_size() const { return payload_offset_; }
danilchap1edb7ab2016-04-20 05:25:10 -070065
66 // Payload.
Danil Chapovalov7d2df3f2018-08-14 17:18:07 +020067 size_t payload_size() const { return payload_size_; }
Danil Chapovalov44450a02021-07-08 13:03:38 +000068 bool has_padding() const { return buffer_[0] & 0x20; }
Danil Chapovalov7d2df3f2018-08-14 17:18:07 +020069 size_t padding_size() const { return padding_size_; }
70 rtc::ArrayView<const uint8_t> payload() const {
71 return rtc::MakeArrayView(data() + payload_offset_, payload_size_);
72 }
Danil Chapovalova3ecb7a2019-12-09 10:24:47 +010073 rtc::CopyOnWriteBuffer PayloadBuffer() const {
74 return buffer_.Slice(payload_offset_, payload_size_);
75 }
danilchap1edb7ab2016-04-20 05:25:10 -070076
77 // Buffer.
Danil Chapovalov7d2df3f2018-08-14 17:18:07 +020078 rtc::CopyOnWriteBuffer Buffer() const { return buffer_; }
79 size_t capacity() const { return buffer_.capacity(); }
80 size_t size() const {
81 return payload_offset_ + payload_size_ + padding_size_;
82 }
83 const uint8_t* data() const { return buffer_.cdata(); }
84 size_t FreeCapacity() const { return capacity() - size(); }
85 size_t MaxPayloadSize() const { return capacity() - headers_size(); }
danilchap1edb7ab2016-04-20 05:25:10 -070086
87 // Reset fields and buffer.
88 void Clear();
89
90 // Header setters.
Danil Chapovalov8769e172017-09-14 14:08:22 +020091 void CopyHeaderFrom(const RtpPacket& packet);
danilchap1edb7ab2016-04-20 05:25:10 -070092 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
Ilya Nikolaevskiya5d952f2019-09-03 11:07:37 +020098 // Fills with zeroes mutable extensions,
Ilya Nikolaevskiy2d821c32019-06-26 14:39:36 +020099 // which are modified after FEC protection is generated.
Ilya Nikolaevskiya5d952f2019-09-03 11:07:37 +0200100 void ZeroMutableExtensions();
Ilya Nikolaevskiy2d821c32019-06-26 14:39:36 +0200101
Anton Sukhanovff25b872019-07-09 13:04:07 -0700102 // 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
danilchap1edb7ab2016-04-20 05:25:10 -0700108 // 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.
Danil Chapovalov7d2df3f2018-08-14 17:18:07 +0200111 void SetCsrcs(rtc::ArrayView<const uint32_t> csrcs);
danilchap1edb7ab2016-04-20 05:25:10 -0700112
113 // Header extensions.
Danil Chapovalov5e57b172016-09-02 19:15:59 +0200114 template <typename Extension>
115 bool HasExtension() const;
Amit Hilbuch77938e62018-12-21 09:23:38 -0800116 bool HasExtension(ExtensionType type) const;
Danil Chapovalov5e57b172016-09-02 19:15:59 +0200117
Danil Chapovalov7d541822021-06-17 15:27:12 +0200118 // 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
Danil Chapovalovc5dd3002018-11-08 15:12:45 +0100123 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;
danilchap1edb7ab2016-04-20 05:25:10 -0700128
Danil Chapovalove19953b2018-10-01 16:12:28 +0200129 // Returns view of the raw extension or empty view on failure.
130 template <typename Extension>
131 rtc::ArrayView<const uint8_t> GetRawExtension() const;
132
danilchap1edb7ab2016-04-20 05:25:10 -0700133 template <typename Extension, typename... Values>
Danil Chapovalovcea92992020-01-17 12:59:15 +0100134 bool SetExtension(const Values&...);
danilchap1edb7ab2016-04-20 05:25:10 -0700135
136 template <typename Extension>
137 bool ReserveExtension();
138
Amit Hilbuch77938e62018-12-21 09:23:38 -0800139 // 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
danilchap1edb7ab2016-04-20 05:25:10 -0700147 // Reserve size_bytes for payload. Returns nullptr on failure.
danilchap07a01b32017-03-29 07:33:13 -0700148 uint8_t* SetPayloadSize(size_t size_bytes);
149 // Same as SetPayloadSize but doesn't guarantee to keep current payload.
danilchap1edb7ab2016-04-20 05:25:10 -0700150 uint8_t* AllocatePayload(size_t size_bytes);
Danil Chapovalovf7fcaf02018-10-10 14:56:01 +0200151
152 bool SetPadding(size_t padding_size);
danilchap1edb7ab2016-04-20 05:25:10 -0700153
Anton Sukhanovff25b872019-07-09 13:04:07 -0700154 // Returns debug string of RTP packet (without detailed extension info).
155 std::string ToString() const;
156
danilchap1edb7ab2016-04-20 05:25:10 -0700157 private:
158 struct ExtensionInfo {
Johannes Kronc5744b82018-09-24 14:50:48 +0200159 explicit ExtensionInfo(uint8_t id) : ExtensionInfo(id, 0, 0) {}
160 ExtensionInfo(uint8_t id, uint8_t length, uint16_t offset)
161 : id(id), length(length), offset(offset) {}
162 uint8_t id;
danilchap1edb7ab2016-04-20 05:25:10 -0700163 uint8_t length;
Johannes Kronc5744b82018-09-24 14:50:48 +0200164 uint16_t offset;
danilchap1edb7ab2016-04-20 05:25:10 -0700165 };
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
Johannes Kronc5744b82018-09-24 14:50:48 +0200171 // 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
Danil Chapovalov527ff1e2018-08-06 19:34:32 +0200179 // 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
Johannes Kron78cdde32018-10-05 10:00:46 +0200183 // 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
Danil Chapovalove15dc582021-01-07 15:24:05 +0100189 uint8_t* WriteAt(size_t offset) { return buffer_.MutableData() + offset; }
190 void WriteAt(size_t offset, uint8_t byte) {
191 buffer_.MutableData()[offset] = byte;
192 }
Anton Sukhanovff25b872019-07-09 13:04:07 -0700193 const uint8_t* ReadAt(size_t offset) const { return buffer_.data() + offset; }
danilchap1edb7ab2016-04-20 05:25:10 -0700194
danilchap1edb7ab2016-04-20 05:25:10 -0700195 // 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
Johannes Kronc5744b82018-09-24 14:50:48 +0200205 ExtensionManager extensions_;
206 std::vector<ExtensionInfo> extension_entries_;
Danil Chapovalov61405bc2018-02-13 13:55:30 +0100207 size_t extensions_size_ = 0; // Unaligned.
Danil Chapovalov31e4e802016-08-03 18:27:40 +0200208 rtc::CopyOnWriteBuffer buffer_;
danilchap1edb7ab2016-04-20 05:25:10 -0700209};
210
Danil Chapovalov5e57b172016-09-02 19:15:59 +0200211template <typename Extension>
Danil Chapovalov8769e172017-09-14 14:08:22 +0200212bool RtpPacket::HasExtension() const {
Amit Hilbuch77938e62018-12-21 09:23:38 -0800213 return HasExtension(Extension::kId);
Danil Chapovalov5e57b172016-09-02 19:15:59 +0200214}
215
Danil Chapovalov7d541822021-06-17 15:27:12 +0200216template <typename Extension>
217bool RtpPacket::IsRegistered() const {
218 return extensions_.IsRegistered(Extension::kId);
219}
220
Danil Chapovalovc5dd3002018-11-08 15:12:45 +0100221template <typename Extension, typename FirstValue, typename... Values>
222bool RtpPacket::GetExtension(FirstValue first, Values... values) const {
danilchap978504e2017-04-06 01:03:53 -0700223 auto raw = FindExtension(Extension::kId);
224 if (raw.empty())
danilchap1edb7ab2016-04-20 05:25:10 -0700225 return false;
Danil Chapovalovc5dd3002018-11-08 15:12:45 +0100226 return Extension::Parse(raw, first, values...);
227}
228
229template <typename Extension>
230absl::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;
danilchap1edb7ab2016-04-20 05:25:10 -0700236}
237
Danil Chapovalove19953b2018-10-01 16:12:28 +0200238template <typename Extension>
239rtc::ArrayView<const uint8_t> RtpPacket::GetRawExtension() const {
240 return FindExtension(Extension::kId);
241}
242
danilchap1edb7ab2016-04-20 05:25:10 -0700243template <typename Extension, typename... Values>
Danil Chapovalovcea92992020-01-17 12:59:15 +0100244bool RtpPacket::SetExtension(const Values&... values) {
erikvargae6b16192017-05-11 02:36:32 -0700245 const size_t value_size = Extension::ValueSize(values...);
erikvargae6b16192017-05-11 02:36:32 -0700246 auto buffer = AllocateExtension(Extension::kId, value_size);
danilchap653063f2017-04-03 06:16:30 -0700247 if (buffer.empty())
danilchap1edb7ab2016-04-20 05:25:10 -0700248 return false;
Danil Chapovalov9bf31582018-06-18 13:48:20 +0200249 return Extension::Write(buffer, values...);
danilchap1edb7ab2016-04-20 05:25:10 -0700250}
251
252template <typename Extension>
Danil Chapovalov8769e172017-09-14 14:08:22 +0200253bool RtpPacket::ReserveExtension() {
danilchap653063f2017-04-03 06:16:30 -0700254 auto buffer = AllocateExtension(Extension::kId, Extension::kValueSizeBytes);
255 if (buffer.empty())
danilchap1edb7ab2016-04-20 05:25:10 -0700256 return false;
danilchap653063f2017-04-03 06:16:30 -0700257 memset(buffer.data(), 0, Extension::kValueSizeBytes);
danilchap1edb7ab2016-04-20 05:25:10 -0700258 return true;
259}
Danil Chapovalov8769e172017-09-14 14:08:22 +0200260
danilchap1edb7ab2016-04-20 05:25:10 -0700261} // namespace webrtc
262
Mirko Bonadei92ea95e2017-09-15 06:47:31 +0200263#endif // MODULES_RTP_RTCP_SOURCE_RTP_PACKET_H_