blob: 64a4bcb0aea49f117cb15b369b06474c7c173b7b [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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020015#include "api/array_view.h"
16#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020017#include "rtc_base/copyonwritebuffer.h"
danilchap1edb7ab2016-04-20 05:25:10 -070018
19namespace webrtc {
danilchap1edb7ab2016-04-20 05:25:10 -070020class RtpHeaderExtensionMap;
21class Random;
22
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;
danilchap772bd8b2017-09-13 03:24:28 -070027 static constexpr int kMaxExtensionHeaders = 14;
danilchap653063f2017-04-03 06:16:30 -070028 static constexpr int kMinExtensionId = 1;
29 static constexpr int kMaxExtensionId = 14;
danilchap1edb7ab2016-04-20 05:25:10 -070030
eladalon87443ee2017-09-13 02:45:15 -070031 // |extensions| required for SetExtension/ReserveExtension functions during
32 // packet creating and used if available in Parse function.
33 // Adding and getting extensions will fail until |extensions| is
34 // provided via constructor or IdentifyExtensions function.
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.
44 bool Parse(const uint8_t* buffer, size_t size);
brandtrb29e6522016-12-21 06:37:18 -080045 bool Parse(rtc::ArrayView<const uint8_t> packet);
danilchap1edb7ab2016-04-20 05:25:10 -070046
47 // Parse and move given buffer into Packet.
Danil Chapovalov31e4e802016-08-03 18:27:40 +020048 bool Parse(rtc::CopyOnWriteBuffer packet);
danilchap1edb7ab2016-04-20 05:25:10 -070049
danilchap70f39a32016-12-16 05:48:18 -080050 // Maps extensions id to their types.
51 void IdentifyExtensions(const ExtensionManager& extensions);
danilchap1edb7ab2016-04-20 05:25:10 -070052
53 // Header.
54 bool Marker() const;
55 uint8_t PayloadType() const;
56 uint16_t SequenceNumber() const;
57 uint32_t Timestamp() const;
58 uint32_t Ssrc() const;
59 std::vector<uint32_t> Csrcs() const;
60
danilchap1edb7ab2016-04-20 05:25:10 -070061 size_t headers_size() const;
62
63 // Payload.
64 size_t payload_size() const;
65 size_t padding_size() const;
danilchap96c15872016-11-21 01:35:29 -080066 rtc::ArrayView<const uint8_t> payload() const;
danilchap1edb7ab2016-04-20 05:25:10 -070067
68 // Buffer.
Danil Chapovalov31e4e802016-08-03 18:27:40 +020069 rtc::CopyOnWriteBuffer Buffer() const;
danilchap1edb7ab2016-04-20 05:25:10 -070070 size_t capacity() const;
71 size_t size() const;
72 const uint8_t* data() const;
73 size_t FreeCapacity() const;
74 size_t MaxPayloadSize() const;
75
76 // Reset fields and buffer.
77 void Clear();
78
79 // Header setters.
Danil Chapovalov8769e172017-09-14 14:08:22 +020080 void CopyHeaderFrom(const RtpPacket& packet);
danilchap1edb7ab2016-04-20 05:25:10 -070081 void SetMarker(bool marker_bit);
82 void SetPayloadType(uint8_t payload_type);
83 void SetSequenceNumber(uint16_t seq_no);
84 void SetTimestamp(uint32_t timestamp);
85 void SetSsrc(uint32_t ssrc);
86
87 // Writes csrc list. Assumes:
88 // a) There is enough room left in buffer.
89 // b) Extension headers, payload or padding data has not already been added.
90 void SetCsrcs(const std::vector<uint32_t>& csrcs);
91
92 // Header extensions.
Danil Chapovalov5e57b172016-09-02 19:15:59 +020093 template <typename Extension>
94 bool HasExtension() const;
95
danilchap1edb7ab2016-04-20 05:25:10 -070096 template <typename Extension, typename... Values>
97 bool GetExtension(Values...) const;
98
99 template <typename Extension, typename... Values>
100 bool SetExtension(Values...);
101
102 template <typename Extension>
103 bool ReserveExtension();
104
105 // Reserve size_bytes for payload. Returns nullptr on failure.
danilchap07a01b32017-03-29 07:33:13 -0700106 uint8_t* SetPayloadSize(size_t size_bytes);
107 // Same as SetPayloadSize but doesn't guarantee to keep current payload.
danilchap1edb7ab2016-04-20 05:25:10 -0700108 uint8_t* AllocatePayload(size_t size_bytes);
danilchap1edb7ab2016-04-20 05:25:10 -0700109 bool SetPadding(uint8_t size_bytes, Random* random);
110
danilchap1edb7ab2016-04-20 05:25:10 -0700111 private:
112 struct ExtensionInfo {
113 ExtensionType type;
114 uint16_t offset;
115 uint8_t length;
116 };
117
118 // Helper function for Parse. Fill header fields using data in given buffer,
119 // but does not touch packet own buffer, leaving packet in invalid state.
120 bool ParseBuffer(const uint8_t* buffer, size_t size);
121
danilchap978504e2017-04-06 01:03:53 -0700122 // Find an extension |type|.
123 // Returns view of the raw extension or empty view on failure.
124 rtc::ArrayView<const uint8_t> FindExtension(ExtensionType type) const;
danilchap1edb7ab2016-04-20 05:25:10 -0700125
Danil Chapovalov527ff1e2018-08-06 19:34:32 +0200126 // Allocates and returns place to store rtp header extension.
127 // Returns empty arrayview on failure.
128 rtc::ArrayView<uint8_t> AllocateRawExtension(int id, size_t length);
129
danilchap653063f2017-04-03 06:16:30 -0700130 // Find or allocate an extension |type|. Returns view of size |length|
131 // to write raw extension to or an empty view on failure.
132 rtc::ArrayView<uint8_t> AllocateExtension(ExtensionType type, size_t length);
danilchap1edb7ab2016-04-20 05:25:10 -0700133
134 uint8_t* WriteAt(size_t offset);
135 void WriteAt(size_t offset, uint8_t byte);
136
danilchap1edb7ab2016-04-20 05:25:10 -0700137 // Header.
138 bool marker_;
139 uint8_t payload_type_;
140 uint8_t padding_size_;
141 uint16_t sequence_number_;
142 uint32_t timestamp_;
143 uint32_t ssrc_;
144 size_t payload_offset_; // Match header size with csrcs and extensions.
145 size_t payload_size_;
146
danilchap1edb7ab2016-04-20 05:25:10 -0700147 ExtensionInfo extension_entries_[kMaxExtensionHeaders];
Danil Chapovalov61405bc2018-02-13 13:55:30 +0100148 size_t extensions_size_ = 0; // Unaligned.
Danil Chapovalov31e4e802016-08-03 18:27:40 +0200149 rtc::CopyOnWriteBuffer buffer_;
danilchap1edb7ab2016-04-20 05:25:10 -0700150};
151
Danil Chapovalov5e57b172016-09-02 19:15:59 +0200152template <typename Extension>
Danil Chapovalov8769e172017-09-14 14:08:22 +0200153bool RtpPacket::HasExtension() const {
danilchap978504e2017-04-06 01:03:53 -0700154 return !FindExtension(Extension::kId).empty();
Danil Chapovalov5e57b172016-09-02 19:15:59 +0200155}
156
danilchap1edb7ab2016-04-20 05:25:10 -0700157template <typename Extension, typename... Values>
Danil Chapovalov8769e172017-09-14 14:08:22 +0200158bool RtpPacket::GetExtension(Values... values) const {
danilchap978504e2017-04-06 01:03:53 -0700159 auto raw = FindExtension(Extension::kId);
160 if (raw.empty())
danilchap1edb7ab2016-04-20 05:25:10 -0700161 return false;
danilchap978504e2017-04-06 01:03:53 -0700162 return Extension::Parse(raw, values...);
danilchap1edb7ab2016-04-20 05:25:10 -0700163}
164
165template <typename Extension, typename... Values>
Danil Chapovalov8769e172017-09-14 14:08:22 +0200166bool RtpPacket::SetExtension(Values... values) {
erikvargae6b16192017-05-11 02:36:32 -0700167 const size_t value_size = Extension::ValueSize(values...);
168 if (value_size == 0 || value_size > 16)
169 return false;
170 auto buffer = AllocateExtension(Extension::kId, value_size);
danilchap653063f2017-04-03 06:16:30 -0700171 if (buffer.empty())
danilchap1edb7ab2016-04-20 05:25:10 -0700172 return false;
Danil Chapovalov9bf31582018-06-18 13:48:20 +0200173 return Extension::Write(buffer, values...);
danilchap1edb7ab2016-04-20 05:25:10 -0700174}
175
176template <typename Extension>
Danil Chapovalov8769e172017-09-14 14:08:22 +0200177bool RtpPacket::ReserveExtension() {
danilchap653063f2017-04-03 06:16:30 -0700178 auto buffer = AllocateExtension(Extension::kId, Extension::kValueSizeBytes);
179 if (buffer.empty())
danilchap1edb7ab2016-04-20 05:25:10 -0700180 return false;
danilchap653063f2017-04-03 06:16:30 -0700181 memset(buffer.data(), 0, Extension::kValueSizeBytes);
danilchap1edb7ab2016-04-20 05:25:10 -0700182 return true;
183}
Danil Chapovalov8769e172017-09-14 14:08:22 +0200184
danilchap1edb7ab2016-04-20 05:25:10 -0700185} // namespace webrtc
186
Mirko Bonadei92ea95e2017-09-15 06:47:31 +0200187#endif // MODULES_RTP_RTCP_SOURCE_RTP_PACKET_H_