blob: 67d8df4894aa0a47c8ecb7370040b7780376b4f1 [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
13#include <vector>
14
Danil Chapovalovc5dd3002018-11-08 15:12:45 +010015#include "absl/types/optional.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020016#include "api/array_view.h"
Johannes Kronc5744b82018-09-24 14:50:48 +020017#include "modules/rtp_rtcp/include/rtp_header_extension_map.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020018#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
Steve Anton10542f22019-01-11 09:11:00 -080019#include "rtc_base/copy_on_write_buffer.h"
danilchap1edb7ab2016-04-20 05:25:10 -070020
21namespace webrtc {
danilchap1edb7ab2016-04-20 05:25:10 -070022
Danil Chapovalov8769e172017-09-14 14:08:22 +020023class RtpPacket {
danilchap1edb7ab2016-04-20 05:25:10 -070024 public:
25 using ExtensionType = RTPExtensionType;
26 using ExtensionManager = RtpHeaderExtensionMap;
danilchap1edb7ab2016-04-20 05:25:10 -070027
eladalon87443ee2017-09-13 02:45:15 -070028 // |extensions| required for SetExtension/ReserveExtension functions during
29 // packet creating and used if available in Parse function.
30 // Adding and getting extensions will fail until |extensions| is
31 // provided via constructor or IdentifyExtensions function.
Danil Chapovalov8769e172017-09-14 14:08:22 +020032 RtpPacket();
33 explicit RtpPacket(const ExtensionManager* extensions);
34 RtpPacket(const RtpPacket&);
35 RtpPacket(const ExtensionManager* extensions, size_t capacity);
36 ~RtpPacket();
eladalon87443ee2017-09-13 02:45:15 -070037
Danil Chapovalov8769e172017-09-14 14:08:22 +020038 RtpPacket& operator=(const RtpPacket&) = default;
eladalon87443ee2017-09-13 02:45:15 -070039
danilchap1edb7ab2016-04-20 05:25:10 -070040 // Parse and copy given buffer into Packet.
41 bool Parse(const uint8_t* buffer, size_t size);
brandtrb29e6522016-12-21 06:37:18 -080042 bool Parse(rtc::ArrayView<const uint8_t> packet);
danilchap1edb7ab2016-04-20 05:25:10 -070043
44 // Parse and move given buffer into Packet.
Danil Chapovalov31e4e802016-08-03 18:27:40 +020045 bool Parse(rtc::CopyOnWriteBuffer packet);
danilchap1edb7ab2016-04-20 05:25:10 -070046
danilchap70f39a32016-12-16 05:48:18 -080047 // Maps extensions id to their types.
48 void IdentifyExtensions(const ExtensionManager& extensions);
danilchap1edb7ab2016-04-20 05:25:10 -070049
50 // Header.
Danil Chapovalov7d2df3f2018-08-14 17:18:07 +020051 bool Marker() const { return marker_; }
52 uint8_t PayloadType() const { return payload_type_; }
53 uint16_t SequenceNumber() const { return sequence_number_; }
54 uint32_t Timestamp() const { return timestamp_; }
55 uint32_t Ssrc() const { return ssrc_; }
danilchap1edb7ab2016-04-20 05:25:10 -070056 std::vector<uint32_t> Csrcs() const;
57
Danil Chapovalov7d2df3f2018-08-14 17:18:07 +020058 size_t headers_size() const { return payload_offset_; }
danilchap1edb7ab2016-04-20 05:25:10 -070059
60 // Payload.
Danil Chapovalov7d2df3f2018-08-14 17:18:07 +020061 size_t payload_size() const { return payload_size_; }
62 size_t padding_size() const { return padding_size_; }
63 rtc::ArrayView<const uint8_t> payload() const {
64 return rtc::MakeArrayView(data() + payload_offset_, payload_size_);
65 }
danilchap1edb7ab2016-04-20 05:25:10 -070066
67 // Buffer.
Danil Chapovalov7d2df3f2018-08-14 17:18:07 +020068 rtc::CopyOnWriteBuffer Buffer() const { return buffer_; }
69 size_t capacity() const { return buffer_.capacity(); }
70 size_t size() const {
71 return payload_offset_ + payload_size_ + padding_size_;
72 }
73 const uint8_t* data() const { return buffer_.cdata(); }
74 size_t FreeCapacity() const { return capacity() - size(); }
75 size_t MaxPayloadSize() const { return capacity() - headers_size(); }
danilchap1edb7ab2016-04-20 05:25:10 -070076
77 // Reset fields and buffer.
78 void Clear();
79
80 // Header setters.
Danil Chapovalov8769e172017-09-14 14:08:22 +020081 void CopyHeaderFrom(const RtpPacket& packet);
danilchap1edb7ab2016-04-20 05:25:10 -070082 void SetMarker(bool marker_bit);
83 void SetPayloadType(uint8_t payload_type);
84 void SetSequenceNumber(uint16_t seq_no);
85 void SetTimestamp(uint32_t timestamp);
86 void SetSsrc(uint32_t ssrc);
87
Ilya Nikolaevskiy2d821c32019-06-26 14:39:36 +020088 // Copies the buffer with zero-ed mutable extensions,
89 // which are modified after FEC protection is generated.
90 void CopyAndZeroMutableExtensions(rtc::ArrayView<uint8_t> buffer) const;
91
danilchap1edb7ab2016-04-20 05:25:10 -070092 // Writes csrc list. Assumes:
93 // a) There is enough room left in buffer.
94 // b) Extension headers, payload or padding data has not already been added.
Danil Chapovalov7d2df3f2018-08-14 17:18:07 +020095 void SetCsrcs(rtc::ArrayView<const uint32_t> csrcs);
danilchap1edb7ab2016-04-20 05:25:10 -070096
97 // Header extensions.
Danil Chapovalov5e57b172016-09-02 19:15:59 +020098 template <typename Extension>
99 bool HasExtension() const;
Amit Hilbuch77938e62018-12-21 09:23:38 -0800100 bool HasExtension(ExtensionType type) const;
Danil Chapovalov5e57b172016-09-02 19:15:59 +0200101
Erik Språng1d46f9c2019-07-02 21:24:47 +0200102 template <typename Extension>
103 bool IsExtensionReserved() const;
104 bool IsExtensionReserved(ExtensionType type) const;
105
Danil Chapovalovc5dd3002018-11-08 15:12:45 +0100106 template <typename Extension, typename FirstValue, typename... Values>
107 bool GetExtension(FirstValue, Values...) const;
108
109 template <typename Extension>
110 absl::optional<typename Extension::value_type> GetExtension() const;
danilchap1edb7ab2016-04-20 05:25:10 -0700111
Danil Chapovalove19953b2018-10-01 16:12:28 +0200112 // Returns view of the raw extension or empty view on failure.
113 template <typename Extension>
114 rtc::ArrayView<const uint8_t> GetRawExtension() const;
115
danilchap1edb7ab2016-04-20 05:25:10 -0700116 template <typename Extension, typename... Values>
117 bool SetExtension(Values...);
118
119 template <typename Extension>
120 bool ReserveExtension();
121
Amit Hilbuch77938e62018-12-21 09:23:38 -0800122 // Find or allocate an extension |type|. Returns view of size |length|
123 // to write raw extension to or an empty view on failure.
124 rtc::ArrayView<uint8_t> AllocateExtension(ExtensionType type, size_t length);
125
126 // Find an extension |type|.
127 // Returns view of the raw extension or empty view on failure.
128 rtc::ArrayView<const uint8_t> FindExtension(ExtensionType type) const;
129
danilchap1edb7ab2016-04-20 05:25:10 -0700130 // Reserve size_bytes for payload. Returns nullptr on failure.
danilchap07a01b32017-03-29 07:33:13 -0700131 uint8_t* SetPayloadSize(size_t size_bytes);
132 // Same as SetPayloadSize but doesn't guarantee to keep current payload.
danilchap1edb7ab2016-04-20 05:25:10 -0700133 uint8_t* AllocatePayload(size_t size_bytes);
Danil Chapovalovf7fcaf02018-10-10 14:56:01 +0200134
135 bool SetPadding(size_t padding_size);
danilchap1edb7ab2016-04-20 05:25:10 -0700136
danilchap1edb7ab2016-04-20 05:25:10 -0700137 private:
138 struct ExtensionInfo {
Johannes Kronc5744b82018-09-24 14:50:48 +0200139 explicit ExtensionInfo(uint8_t id) : ExtensionInfo(id, 0, 0) {}
140 ExtensionInfo(uint8_t id, uint8_t length, uint16_t offset)
141 : id(id), length(length), offset(offset) {}
142 uint8_t id;
danilchap1edb7ab2016-04-20 05:25:10 -0700143 uint8_t length;
Johannes Kronc5744b82018-09-24 14:50:48 +0200144 uint16_t offset;
danilchap1edb7ab2016-04-20 05:25:10 -0700145 };
146
147 // Helper function for Parse. Fill header fields using data in given buffer,
148 // but does not touch packet own buffer, leaving packet in invalid state.
149 bool ParseBuffer(const uint8_t* buffer, size_t size);
150
Johannes Kronc5744b82018-09-24 14:50:48 +0200151 // Returns pointer to extension info for a given id. Returns nullptr if not
152 // found.
153 const ExtensionInfo* FindExtensionInfo(int id) const;
154
155 // Returns reference to extension info for a given id. Creates a new entry
156 // with the specified id if not found.
157 ExtensionInfo& FindOrCreateExtensionInfo(int id);
158
Danil Chapovalov527ff1e2018-08-06 19:34:32 +0200159 // Allocates and returns place to store rtp header extension.
160 // Returns empty arrayview on failure.
161 rtc::ArrayView<uint8_t> AllocateRawExtension(int id, size_t length);
162
Johannes Kron78cdde32018-10-05 10:00:46 +0200163 // Promotes existing one-byte header extensions to two-byte header extensions
164 // by rewriting the data and updates the corresponding extension offsets.
165 void PromoteToTwoByteHeaderExtension();
166
167 uint16_t SetExtensionLengthMaybeAddZeroPadding(size_t extensions_offset);
168
Danil Chapovalov7d2df3f2018-08-14 17:18:07 +0200169 uint8_t* WriteAt(size_t offset) { return buffer_.data() + offset; }
170 void WriteAt(size_t offset, uint8_t byte) { buffer_.data()[offset] = byte; }
danilchap1edb7ab2016-04-20 05:25:10 -0700171
danilchap1edb7ab2016-04-20 05:25:10 -0700172 // Header.
173 bool marker_;
174 uint8_t payload_type_;
175 uint8_t padding_size_;
176 uint16_t sequence_number_;
177 uint32_t timestamp_;
178 uint32_t ssrc_;
179 size_t payload_offset_; // Match header size with csrcs and extensions.
180 size_t payload_size_;
181
Johannes Kronc5744b82018-09-24 14:50:48 +0200182 ExtensionManager extensions_;
183 std::vector<ExtensionInfo> extension_entries_;
Danil Chapovalov61405bc2018-02-13 13:55:30 +0100184 size_t extensions_size_ = 0; // Unaligned.
Danil Chapovalov31e4e802016-08-03 18:27:40 +0200185 rtc::CopyOnWriteBuffer buffer_;
danilchap1edb7ab2016-04-20 05:25:10 -0700186};
187
Danil Chapovalov5e57b172016-09-02 19:15:59 +0200188template <typename Extension>
Danil Chapovalov8769e172017-09-14 14:08:22 +0200189bool RtpPacket::HasExtension() const {
Amit Hilbuch77938e62018-12-21 09:23:38 -0800190 return HasExtension(Extension::kId);
Danil Chapovalov5e57b172016-09-02 19:15:59 +0200191}
192
Erik Språng1d46f9c2019-07-02 21:24:47 +0200193template <typename Extension>
194bool RtpPacket::IsExtensionReserved() const {
195 return IsExtensionReserved(Extension::kId);
196}
197
Danil Chapovalovc5dd3002018-11-08 15:12:45 +0100198template <typename Extension, typename FirstValue, typename... Values>
199bool RtpPacket::GetExtension(FirstValue first, Values... values) const {
danilchap978504e2017-04-06 01:03:53 -0700200 auto raw = FindExtension(Extension::kId);
201 if (raw.empty())
danilchap1edb7ab2016-04-20 05:25:10 -0700202 return false;
Danil Chapovalovc5dd3002018-11-08 15:12:45 +0100203 return Extension::Parse(raw, first, values...);
204}
205
206template <typename Extension>
207absl::optional<typename Extension::value_type> RtpPacket::GetExtension() const {
208 absl::optional<typename Extension::value_type> result;
209 auto raw = FindExtension(Extension::kId);
210 if (raw.empty() || !Extension::Parse(raw, &result.emplace()))
211 result = absl::nullopt;
212 return result;
danilchap1edb7ab2016-04-20 05:25:10 -0700213}
214
Danil Chapovalove19953b2018-10-01 16:12:28 +0200215template <typename Extension>
216rtc::ArrayView<const uint8_t> RtpPacket::GetRawExtension() const {
217 return FindExtension(Extension::kId);
218}
219
danilchap1edb7ab2016-04-20 05:25:10 -0700220template <typename Extension, typename... Values>
Danil Chapovalov8769e172017-09-14 14:08:22 +0200221bool RtpPacket::SetExtension(Values... values) {
erikvargae6b16192017-05-11 02:36:32 -0700222 const size_t value_size = Extension::ValueSize(values...);
erikvargae6b16192017-05-11 02:36:32 -0700223 auto buffer = AllocateExtension(Extension::kId, value_size);
danilchap653063f2017-04-03 06:16:30 -0700224 if (buffer.empty())
danilchap1edb7ab2016-04-20 05:25:10 -0700225 return false;
Danil Chapovalov9bf31582018-06-18 13:48:20 +0200226 return Extension::Write(buffer, values...);
danilchap1edb7ab2016-04-20 05:25:10 -0700227}
228
229template <typename Extension>
Danil Chapovalov8769e172017-09-14 14:08:22 +0200230bool RtpPacket::ReserveExtension() {
danilchap653063f2017-04-03 06:16:30 -0700231 auto buffer = AllocateExtension(Extension::kId, Extension::kValueSizeBytes);
232 if (buffer.empty())
danilchap1edb7ab2016-04-20 05:25:10 -0700233 return false;
danilchap653063f2017-04-03 06:16:30 -0700234 memset(buffer.data(), 0, Extension::kValueSizeBytes);
danilchap1edb7ab2016-04-20 05:25:10 -0700235 return true;
236}
Danil Chapovalov8769e172017-09-14 14:08:22 +0200237
danilchap1edb7ab2016-04-20 05:25:10 -0700238} // namespace webrtc
239
Mirko Bonadei92ea95e2017-09-15 06:47:31 +0200240#endif // MODULES_RTP_RTCP_SOURCE_RTP_PACKET_H_