11#include <promeki/config.h>
12#if PROMEKI_ENABLE_NETWORK
19PROMEKI_NAMESPACE_BEGIN
64class RtpPacket :
public BufferView {
67 using List = promeki::List<RtpPacket>;
71 using Queue = promeki::Queue<RtpPacket>;
74 using SizeList = promeki::List<size_t>;
77 static constexpr size_t HeaderSize = 12;
80 RtpPacket() =
default;
88 RtpPacket(Buffer buf,
size_t offset,
size_t size) : BufferView(std::move(buf), offset, size) {}
95 bool isNull()
const {
return data() ==
nullptr; }
105 bool isValid()
const {
106 if (data() ==
nullptr)
return false;
107 if (size() < HeaderSize)
return false;
108 if (((data()[0] >> 6) & 0x03) != 2)
return false;
109 return headerSize() != 0;
121 explicit RtpPacket(
size_t packetSize) : BufferView(Buffer(packetSize), 0, packetSize) {
122 std::memset(data(), 0, packetSize);
136 static List createList(
size_t count,
size_t packetSize) {
138 if (count == 0 || packetSize == 0)
return ret;
139 size_t totalSize = count * packetSize;
149 auto buf = Buffer(totalSize, 16);
150 std::memset(buf.data(), 0, totalSize);
152 for (
size_t i = 0; i < count; ++i) {
153 RtpPacket pkt(buf, i * packetSize, packetSize);
155 ret.pushToBack(std::move(pkt));
170 static List createList(
const SizeList &sizes) {
172 if (sizes.isEmpty())
return ret;
173 size_t totalSize = 0;
174 for (
size_t i = 0; i < sizes.size(); ++i) totalSize += sizes[i];
175 if (totalSize == 0)
return ret;
180 auto buf = Buffer(totalSize, 16);
181 std::memset(buf.data(), 0, totalSize);
182 ret.reserve(sizes.size());
184 for (
size_t i = 0; i < sizes.size(); ++i) {
185 RtpPacket pkt(buf, offset, sizes[i]);
186 if (sizes[i] >= HeaderSize) pkt.setVersion(2);
187 ret.pushToBack(std::move(pkt));
194 uint8_t version()
const {
return (hdr()[0] >> 6) & 0x03; }
197 void setVersion(uint8_t v) { hdr()[0] = (hdr()[0] & 0x3F) | ((v & 0x03) << 6); }
200 bool padding()
const {
return (hdr()[0] >> 5) & 0x01; }
203 void setPadding(
bool p) { hdr()[0] = (hdr()[0] & 0xDF) | (p ? 0x20 : 0x00); }
206 bool extension()
const {
return (hdr()[0] >> 4) & 0x01; }
209 void setExtension(
bool x) { hdr()[0] = (hdr()[0] & 0xEF) | (x ? 0x10 : 0x00); }
212 uint8_t csrcCount()
const {
return hdr()[0] & 0x0F; }
215 bool marker()
const {
return (hdr()[1] >> 7) & 0x01; }
218 void setMarker(
bool m) { hdr()[1] = (hdr()[1] & 0x7F) | (m ? 0x80 : 0x00); }
221 uint8_t payloadType()
const {
return hdr()[1] & 0x7F; }
224 void setPayloadType(uint8_t pt) { hdr()[1] = (hdr()[1] & 0x80) | (pt & 0x7F); }
227 uint16_t sequenceNumber()
const {
return (
static_cast<uint16_t
>(hdr()[2]) << 8) | hdr()[3]; }
230 void setSequenceNumber(uint16_t seq) {
231 hdr()[2] =
static_cast<uint8_t
>(seq >> 8);
232 hdr()[3] =
static_cast<uint8_t
>(seq & 0xFF);
236 uint32_t timestamp()
const {
237 return (
static_cast<uint32_t
>(hdr()[4]) << 24) | (
static_cast<uint32_t
>(hdr()[5]) << 16) |
238 (
static_cast<uint32_t
>(hdr()[6]) << 8) |
static_cast<uint32_t
>(hdr()[7]);
242 void setTimestamp(uint32_t ts) {
243 hdr()[4] =
static_cast<uint8_t
>((ts >> 24) & 0xFF);
244 hdr()[5] =
static_cast<uint8_t
>((ts >> 16) & 0xFF);
245 hdr()[6] =
static_cast<uint8_t
>((ts >> 8) & 0xFF);
246 hdr()[7] =
static_cast<uint8_t
>(ts & 0xFF);
250 uint32_t ssrc()
const {
251 return (
static_cast<uint32_t
>(hdr()[8]) << 24) | (
static_cast<uint32_t
>(hdr()[9]) << 16) |
252 (
static_cast<uint32_t
>(hdr()[10]) << 8) |
static_cast<uint32_t
>(hdr()[11]);
256 void setSsrc(uint32_t s) {
257 hdr()[8] =
static_cast<uint8_t
>((s >> 24) & 0xFF);
258 hdr()[9] =
static_cast<uint8_t
>((s >> 16) & 0xFF);
259 hdr()[10] =
static_cast<uint8_t
>((s >> 8) & 0xFF);
260 hdr()[11] =
static_cast<uint8_t
>(s & 0xFF);
272 size_t headerSize()
const {
273 if (size() < HeaderSize)
return 0;
274 size_t hs = HeaderSize + csrcCount() * 4;
275 if (hs > size())
return 0;
278 if (hs + 4 > size())
return 0;
279 const uint8_t *ext = data() + hs;
280 uint16_t extLen = (
static_cast<uint16_t
>(ext[2]) << 8) | ext[3];
281 hs += 4 + extLen * 4;
282 if (hs > size())
return 0;
291 uint16_t extensionProfile()
const {
292 if (!extension())
return 0;
293 size_t extOffset = HeaderSize + csrcCount() * 4;
294 if (extOffset + 4 > size())
return 0;
295 const uint8_t *ext = data() + extOffset;
296 return (
static_cast<uint16_t
>(ext[0]) << 8) | ext[1];
303 uint16_t extensionLength()
const {
304 if (!extension())
return 0;
305 size_t extOffset = HeaderSize + csrcCount() * 4;
306 if (extOffset + 4 > size())
return 0;
307 const uint8_t *ext = data() + extOffset;
308 return (
static_cast<uint16_t
>(ext[2]) << 8) | ext[3];
317 const uint8_t *payload()
const {
318 size_t hs = headerSize();
319 if (hs == 0 || hs >= size())
return nullptr;
325 size_t hs = headerSize();
326 if (hs == 0 || hs >= size())
return nullptr;
336 size_t payloadSize()
const {
337 size_t hs = headerSize();
338 if (hs == 0 || hs >= size())
return 0;
348 if (isNull())
return;
349 std::memset(data(), 0, size());
376 TimeStamp arrivalSteady;
379 const uint8_t *hdr()
const {
380 assert(data() !=
nullptr && size() >= HeaderSize);
384 assert(data() !=
nullptr && size() >= HeaderSize);