blob: 6981eabc254f09d5314fbf4f875377d38f04ea4c [file] [log] [blame]
* Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
#include <vector>
#include "webrtc/base/basictypes.h"
#include "webrtc/base/copyonwritebuffer.h"
#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
namespace webrtc {
struct RTPHeader;
class RtpHeaderExtensionMap;
class Random;
namespace rtp {
class Packet {
using ExtensionType = RTPExtensionType;
using ExtensionManager = RtpHeaderExtensionMap;
static constexpr size_t kMaxExtensionHeaders = 14;
// Parse and copy given buffer into Packet.
bool Parse(const uint8_t* buffer, size_t size);
// Parse and move given buffer into Packet.
bool Parse(rtc::CopyOnWriteBuffer packet);
// Maps parsed extensions to their types to allow use of GetExtension.
// Used after parsing when |extensions| can't be provided until base rtp
// header is parsed.
void IdentifyExtensions(const ExtensionManager* extensions);
// Header.
bool Marker() const;
uint8_t PayloadType() const;
uint16_t SequenceNumber() const;
uint32_t Timestamp() const;
uint32_t Ssrc() const;
std::vector<uint32_t> Csrcs() const;
// TODO(danilchap): Remove this function when all code update to use RtpPacket
// directly. Function is there just for easier backward compatibilty.
void GetHeader(RTPHeader* header) const;
size_t headers_size() const;
// Payload.
size_t payload_size() const;
size_t padding_size() const;
const uint8_t* payload() const;
// Buffer.
rtc::CopyOnWriteBuffer Buffer() const;
size_t capacity() const;
size_t size() const;
const uint8_t* data() const;
size_t FreeCapacity() const;
size_t MaxPayloadSize() const;
// Reset fields and buffer.
void Clear();
// Header setters.
void CopyHeaderFrom(const Packet& packet);
void SetMarker(bool marker_bit);
void SetPayloadType(uint8_t payload_type);
void SetSequenceNumber(uint16_t seq_no);
void SetTimestamp(uint32_t timestamp);
void SetSsrc(uint32_t ssrc);
// Writes csrc list. Assumes:
// a) There is enough room left in buffer.
// b) Extension headers, payload or padding data has not already been added.
void SetCsrcs(const std::vector<uint32_t>& csrcs);
// Header extensions.
template <typename Extension>
bool HasExtension() const;
template <typename Extension, typename... Values>
bool GetExtension(Values...) const;
template <typename Extension, typename... Values>
bool SetExtension(Values...);
template <typename Extension>
bool ReserveExtension();
// Reserve size_bytes for payload. Returns nullptr on failure.
uint8_t* AllocatePayload(size_t size_bytes);
void SetPayloadSize(size_t size_bytes);
bool SetPadding(uint8_t size_bytes, Random* random);
// |extensions| required for SetExtension/ReserveExtension functions during
// packet creating and used if available in Parse function.
// Adding and getting extensions will fail until |extensions| is
// provided via constructor or IdentifyExtensions function.
explicit Packet(const ExtensionManager* extensions);
Packet(const Packet&) = default;
Packet(const ExtensionManager* extensions, size_t capacity);
virtual ~Packet();
Packet& operator=(const Packet&) = default;
struct ExtensionInfo {
ExtensionType type;
uint16_t offset;
uint8_t length;
// Helper function for Parse. Fill header fields using data in given buffer,
// but does not touch packet own buffer, leaving packet in invalid state.
bool ParseBuffer(const uint8_t* buffer, size_t size);
// Find an extension based on the type field of the parameter.
// If found, length field would be validated, the offset field will be set
// and true returned,
// otherwise the parameter will be unchanged and false is returned.
bool FindExtension(ExtensionType type,
uint8_t length,
uint16_t* offset) const;
// Find or allocate an extension, based on the type field of the parameter.
// If found, the length field be checked against what is already registered
// and the offset field will be set, then true is returned. If allocated, the
// length field will be used for allocation and the offset update to indicate
// position, the true is returned.
// If not found and allocations fails, false is returned and parameter remains
// unchanged.
bool AllocateExtension(ExtensionType type, uint8_t length, uint16_t* offset);
uint8_t* WriteAt(size_t offset);
void WriteAt(size_t offset, uint8_t byte);
const ExtensionManager* extensions_;
// Header.
bool marker_;
uint8_t payload_type_;
uint8_t padding_size_;
uint16_t sequence_number_;
uint32_t timestamp_;
uint32_t ssrc_;
size_t payload_offset_; // Match header size with csrcs and extensions.
size_t payload_size_;
uint8_t num_extensions_ = 0;
ExtensionInfo extension_entries_[kMaxExtensionHeaders];
uint16_t extensions_size_ = 0; // Unaligned.
rtc::CopyOnWriteBuffer buffer_;
Packet() = delete;
template <typename Extension>
bool Packet::HasExtension() const {
uint16_t offset = 0;
return FindExtension(Extension::kId, Extension::kValueSizeBytes, &offset);
template <typename Extension, typename... Values>
bool Packet::GetExtension(Values... values) const {
uint16_t offset = 0;
if (!FindExtension(Extension::kId, Extension::kValueSizeBytes, &offset))
return false;
return Extension::Parse(data() + offset, values...);
template <typename Extension, typename... Values>
bool Packet::SetExtension(Values... values) {
uint16_t offset = 0;
if (!AllocateExtension(Extension::kId, Extension::kValueSizeBytes, &offset))
return false;
return Extension::Write(WriteAt(offset), values...);
template <typename Extension>
bool Packet::ReserveExtension() {
uint16_t offset = 0;
if (!AllocateExtension(Extension::kId, Extension::kValueSizeBytes, &offset))
return false;
memset(WriteAt(offset), 0, Extension::kValueSizeBytes);
return true;
} // namespace rtp
} // namespace webrtc