|  | /* | 
|  | *  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. | 
|  | */ | 
|  | #ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_PACKET_H_ | 
|  | #define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_PACKET_H_ | 
|  |  | 
|  | #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 { | 
|  | public: | 
|  | 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); | 
|  |  | 
|  | protected: | 
|  | // |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; | 
|  |  | 
|  | private: | 
|  | 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 | 
|  |  | 
|  | #endif  // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_PACKET_H_ |