blob: fb19815b59343ee8ed35dcabf45936ea29f4236f [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 */
10#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_PACKET_H_
11#define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_PACKET_H_
12
13#include <vector>
14
kwiberg529662a2017-09-04 05:43:17 -070015#include "webrtc/api/array_view.h"
danilchap1edb7ab2016-04-20 05:25:10 -070016#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
Edward Lemurc20978e2017-07-06 19:44:34 +020017#include "webrtc/rtc_base/basictypes.h"
18#include "webrtc/rtc_base/copyonwritebuffer.h"
danilchap1edb7ab2016-04-20 05:25:10 -070019
20namespace webrtc {
danilchap1edb7ab2016-04-20 05:25:10 -070021class RtpHeaderExtensionMap;
22class Random;
23
24namespace rtp {
25class Packet {
26 public:
27 using ExtensionType = RTPExtensionType;
28 using ExtensionManager = RtpHeaderExtensionMap;
29 static constexpr size_t kMaxExtensionHeaders = 14;
danilchap653063f2017-04-03 06:16:30 -070030 static constexpr int kMinExtensionId = 1;
31 static constexpr int kMaxExtensionId = 14;
danilchap1edb7ab2016-04-20 05:25:10 -070032
33 // Parse and copy given buffer into Packet.
34 bool Parse(const uint8_t* buffer, size_t size);
brandtrb29e6522016-12-21 06:37:18 -080035 bool Parse(rtc::ArrayView<const uint8_t> packet);
danilchap1edb7ab2016-04-20 05:25:10 -070036
37 // Parse and move given buffer into Packet.
Danil Chapovalov31e4e802016-08-03 18:27:40 +020038 bool Parse(rtc::CopyOnWriteBuffer packet);
danilchap1edb7ab2016-04-20 05:25:10 -070039
danilchap70f39a32016-12-16 05:48:18 -080040 // Maps extensions id to their types.
41 void IdentifyExtensions(const ExtensionManager& extensions);
danilchap1edb7ab2016-04-20 05:25:10 -070042
43 // Header.
44 bool Marker() const;
45 uint8_t PayloadType() const;
46 uint16_t SequenceNumber() const;
47 uint32_t Timestamp() const;
48 uint32_t Ssrc() const;
49 std::vector<uint32_t> Csrcs() const;
50
danilchap1edb7ab2016-04-20 05:25:10 -070051 size_t headers_size() const;
52
53 // Payload.
54 size_t payload_size() const;
55 size_t padding_size() const;
danilchap96c15872016-11-21 01:35:29 -080056 rtc::ArrayView<const uint8_t> payload() const;
danilchap1edb7ab2016-04-20 05:25:10 -070057
58 // Buffer.
Danil Chapovalov31e4e802016-08-03 18:27:40 +020059 rtc::CopyOnWriteBuffer Buffer() const;
danilchap1edb7ab2016-04-20 05:25:10 -070060 size_t capacity() const;
61 size_t size() const;
62 const uint8_t* data() const;
63 size_t FreeCapacity() const;
64 size_t MaxPayloadSize() const;
65
66 // Reset fields and buffer.
67 void Clear();
68
69 // Header setters.
Danil Chapovalov31e4e802016-08-03 18:27:40 +020070 void CopyHeaderFrom(const Packet& packet);
danilchap1edb7ab2016-04-20 05:25:10 -070071 void SetMarker(bool marker_bit);
72 void SetPayloadType(uint8_t payload_type);
73 void SetSequenceNumber(uint16_t seq_no);
74 void SetTimestamp(uint32_t timestamp);
75 void SetSsrc(uint32_t ssrc);
76
77 // Writes csrc list. Assumes:
78 // a) There is enough room left in buffer.
79 // b) Extension headers, payload or padding data has not already been added.
80 void SetCsrcs(const std::vector<uint32_t>& csrcs);
81
82 // Header extensions.
Danil Chapovalov5e57b172016-09-02 19:15:59 +020083 template <typename Extension>
84 bool HasExtension() const;
85
danilchap1edb7ab2016-04-20 05:25:10 -070086 template <typename Extension, typename... Values>
87 bool GetExtension(Values...) const;
88
89 template <typename Extension, typename... Values>
90 bool SetExtension(Values...);
91
92 template <typename Extension>
93 bool ReserveExtension();
94
danilchap653063f2017-04-03 06:16:30 -070095 // Following 4 helpers identify rtp header extension by |id| negotiated with
96 // remote peer and written in an rtp packet.
97 bool HasRawExtension(int id) const;
98
99 // Returns place where extension with |id| is stored.
100 // Returns empty arrayview if extension is not present.
101 rtc::ArrayView<const uint8_t> GetRawExtension(int id) const;
102
103 // Allocates and store header extension. Returns true on success.
104 bool SetRawExtension(int id, rtc::ArrayView<const uint8_t> data);
105
106 // Allocates and returns place to store rtp header extension.
107 // Returns empty arrayview on failure.
108 rtc::ArrayView<uint8_t> AllocateRawExtension(int id, size_t length);
109
danilchap1edb7ab2016-04-20 05:25:10 -0700110 // Reserve size_bytes for payload. Returns nullptr on failure.
danilchap07a01b32017-03-29 07:33:13 -0700111 uint8_t* SetPayloadSize(size_t size_bytes);
112 // Same as SetPayloadSize but doesn't guarantee to keep current payload.
danilchap1edb7ab2016-04-20 05:25:10 -0700113 uint8_t* AllocatePayload(size_t size_bytes);
danilchap1edb7ab2016-04-20 05:25:10 -0700114 bool SetPadding(uint8_t size_bytes, Random* random);
115
116 protected:
117 // |extensions| required for SetExtension/ReserveExtension functions during
118 // packet creating and used if available in Parse function.
119 // Adding and getting extensions will fail until |extensions| is
120 // provided via constructor or IdentifyExtensions function.
danilchap70f39a32016-12-16 05:48:18 -0800121 Packet();
danilchap1edb7ab2016-04-20 05:25:10 -0700122 explicit Packet(const ExtensionManager* extensions);
nisse76e62b02017-05-31 02:24:52 -0700123 Packet(const Packet&);
danilchap1edb7ab2016-04-20 05:25:10 -0700124 Packet(const ExtensionManager* extensions, size_t capacity);
danilchapce251812017-09-11 12:24:41 -0700125 ~Packet();
danilchap1edb7ab2016-04-20 05:25:10 -0700126
Danil Chapovalov31e4e802016-08-03 18:27:40 +0200127 Packet& operator=(const Packet&) = default;
128
danilchap1edb7ab2016-04-20 05:25:10 -0700129 private:
130 struct ExtensionInfo {
131 ExtensionType type;
132 uint16_t offset;
133 uint8_t length;
134 };
135
136 // Helper function for Parse. Fill header fields using data in given buffer,
137 // but does not touch packet own buffer, leaving packet in invalid state.
138 bool ParseBuffer(const uint8_t* buffer, size_t size);
139
danilchap978504e2017-04-06 01:03:53 -0700140 // Find an extension |type|.
141 // Returns view of the raw extension or empty view on failure.
142 rtc::ArrayView<const uint8_t> FindExtension(ExtensionType type) const;
danilchap1edb7ab2016-04-20 05:25:10 -0700143
danilchap653063f2017-04-03 06:16:30 -0700144 // Find or allocate an extension |type|. Returns view of size |length|
145 // to write raw extension to or an empty view on failure.
146 rtc::ArrayView<uint8_t> AllocateExtension(ExtensionType type, size_t length);
danilchap1edb7ab2016-04-20 05:25:10 -0700147
148 uint8_t* WriteAt(size_t offset);
149 void WriteAt(size_t offset, uint8_t byte);
150
danilchap1edb7ab2016-04-20 05:25:10 -0700151 // Header.
152 bool marker_;
153 uint8_t payload_type_;
154 uint8_t padding_size_;
155 uint16_t sequence_number_;
156 uint32_t timestamp_;
157 uint32_t ssrc_;
158 size_t payload_offset_; // Match header size with csrcs and extensions.
159 size_t payload_size_;
160
danilchap1edb7ab2016-04-20 05:25:10 -0700161 ExtensionInfo extension_entries_[kMaxExtensionHeaders];
162 uint16_t extensions_size_ = 0; // Unaligned.
Danil Chapovalov31e4e802016-08-03 18:27:40 +0200163 rtc::CopyOnWriteBuffer buffer_;
danilchap1edb7ab2016-04-20 05:25:10 -0700164};
165
Danil Chapovalov5e57b172016-09-02 19:15:59 +0200166template <typename Extension>
167bool Packet::HasExtension() const {
danilchap978504e2017-04-06 01:03:53 -0700168 return !FindExtension(Extension::kId).empty();
Danil Chapovalov5e57b172016-09-02 19:15:59 +0200169}
170
danilchap1edb7ab2016-04-20 05:25:10 -0700171template <typename Extension, typename... Values>
172bool Packet::GetExtension(Values... values) const {
danilchap978504e2017-04-06 01:03:53 -0700173 auto raw = FindExtension(Extension::kId);
174 if (raw.empty())
danilchap1edb7ab2016-04-20 05:25:10 -0700175 return false;
danilchap978504e2017-04-06 01:03:53 -0700176 return Extension::Parse(raw, values...);
danilchap1edb7ab2016-04-20 05:25:10 -0700177}
178
179template <typename Extension, typename... Values>
180bool Packet::SetExtension(Values... values) {
erikvargae6b16192017-05-11 02:36:32 -0700181 const size_t value_size = Extension::ValueSize(values...);
182 if (value_size == 0 || value_size > 16)
183 return false;
184 auto buffer = AllocateExtension(Extension::kId, value_size);
danilchap653063f2017-04-03 06:16:30 -0700185 if (buffer.empty())
danilchap1edb7ab2016-04-20 05:25:10 -0700186 return false;
danilchap653063f2017-04-03 06:16:30 -0700187 return Extension::Write(buffer.data(), values...);
danilchap1edb7ab2016-04-20 05:25:10 -0700188}
189
190template <typename Extension>
191bool Packet::ReserveExtension() {
danilchap653063f2017-04-03 06:16:30 -0700192 auto buffer = AllocateExtension(Extension::kId, Extension::kValueSizeBytes);
193 if (buffer.empty())
danilchap1edb7ab2016-04-20 05:25:10 -0700194 return false;
danilchap653063f2017-04-03 06:16:30 -0700195 memset(buffer.data(), 0, Extension::kValueSizeBytes);
danilchap1edb7ab2016-04-20 05:25:10 -0700196 return true;
197}
198} // namespace rtp
199} // namespace webrtc
200
201#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_PACKET_H_