From cd349cd98d7a5243baeb68622159c65ba5e2ab95 Mon Sep 17 00:00:00 2001 From: dijunkun Date: Wed, 22 Jan 2025 17:32:24 +0800 Subject: [PATCH] [feat] rewrite rtp module --- src/common/copy_on_write_buffer.h | 46 + src/rtp/rtp_packet/rtp_codec.h | 2 +- src/rtp/rtp_packet/rtp_header.h | 60 +- src/rtp/rtp_packet/rtp_packet.cc | 787 ++++++++++++++++ src/rtp/rtp_packet/rtp_packet.cpp | 847 ++---------------- src/rtp/rtp_packet/rtp_packet.h | 266 +----- src/rtp/rtp_packet/rtp_packet.hxx | 484 ++++++++++ src/rtp/rtp_packet/rtp_packet_received.cpp | 21 +- src/rtp/rtp_packetizer/rtp_packetizer.cpp | 11 + src/rtp/rtp_packetizer/rtp_packetizer.h | 25 + src/rtp/rtp_packetizer/rtp_packetizer_av1.cpp | 0 src/rtp/rtp_packetizer/rtp_packetizer_av1.h | 0 .../rtp_packetizer/rtp_packetizer_generic.cpp | 0 .../rtp_packetizer/rtp_packetizer_generic.h | 0 .../rtp_packetizer/rtp_packetizer_h264.cpp | 266 ++++++ src/rtp/rtp_packetizer/rtp_packetizer_h264.h | 45 + 16 files changed, 1858 insertions(+), 1002 deletions(-) create mode 100644 src/common/copy_on_write_buffer.h create mode 100644 src/rtp/rtp_packet/rtp_packet.cc create mode 100644 src/rtp/rtp_packet/rtp_packet.hxx create mode 100644 src/rtp/rtp_packetizer/rtp_packetizer.cpp create mode 100644 src/rtp/rtp_packetizer/rtp_packetizer.h create mode 100644 src/rtp/rtp_packetizer/rtp_packetizer_av1.cpp create mode 100644 src/rtp/rtp_packetizer/rtp_packetizer_av1.h create mode 100644 src/rtp/rtp_packetizer/rtp_packetizer_generic.cpp create mode 100644 src/rtp/rtp_packetizer/rtp_packetizer_generic.h create mode 100644 src/rtp/rtp_packetizer/rtp_packetizer_h264.cpp create mode 100644 src/rtp/rtp_packetizer/rtp_packetizer_h264.h diff --git a/src/common/copy_on_write_buffer.h b/src/common/copy_on_write_buffer.h new file mode 100644 index 0000000..fb3b69b --- /dev/null +++ b/src/common/copy_on_write_buffer.h @@ -0,0 +1,46 @@ +/* + * @Author: DI JUNKUN + * @Date: 2025-01-22 + * Copyright (c) 2025 by DI JUNKUN, All Rights Reserved. + */ + +#ifndef _COPY_ON_WRITE_BUFFER_H_ +#define _COPY_ON_WRITE_BUFFER_H_ + +#include +#include + +class CopyOnWriteBuffer { + public: + CopyOnWriteBuffer() = default; + CopyOnWriteBuffer(const CopyOnWriteBuffer& other) = default; + CopyOnWriteBuffer(CopyOnWriteBuffer&& other) noexcept = default; + CopyOnWriteBuffer& operator=(const CopyOnWriteBuffer& other) = default; + CopyOnWriteBuffer& operator=(CopyOnWriteBuffer&& other) noexcept = default; + + void SetData(const uint8_t* data, size_t size) { + buffer_ = std::make_shared>(data, data + size); + } + + const uint8_t* data() const { return buffer_ ? buffer_->data() : nullptr; } + + size_t size() const { return buffer_ ? buffer_->size() : 0; } + + uint8_t& operator[](size_t index) { + EnsureUnique(); + return (*buffer_)[index]; + } + + const uint8_t& operator[](size_t index) const { return (*buffer_)[index]; } + + private: + void EnsureUnique() { + if (!buffer_.unique()) { + buffer_ = std::make_shared>(*buffer_); + } + } + + std::shared_ptr> buffer_; +}; + +#endif \ No newline at end of file diff --git a/src/rtp/rtp_packet/rtp_codec.h b/src/rtp/rtp_packet/rtp_codec.h index f61ea26..d014f63 100644 --- a/src/rtp/rtp_packet/rtp_codec.h +++ b/src/rtp/rtp_packet/rtp_codec.h @@ -36,7 +36,7 @@ class RtpCodec { uint8_t version_ = 0; bool has_padding_ = false; bool has_extension_ = false; - uint32_t total_csrc_number_ = 0; + uint32_t csrc_count_ = 0; bool marker_ = false; uint32_t payload_type_ = 0; uint16_t sequence_number_ = 0; diff --git a/src/rtp/rtp_packet/rtp_header.h b/src/rtp/rtp_packet/rtp_header.h index 3de3ce7..a0efc4d 100644 --- a/src/rtp/rtp_packet/rtp_header.h +++ b/src/rtp/rtp_packet/rtp_header.h @@ -7,40 +7,58 @@ #ifndef _RTP_HEADER_H_ #define _RTP_HEADER_H_ +#include #include #include #include #include -#include "api/units/timestamp.h" +static constexpr int kMaxRtpCsrcSize = 15; +static constexpr uint8_t kRtpVersion = 2; -static constexpr int kAbsSendTimeFraction = 18; +struct RTPHeaderExtension { + RTPHeaderExtension(); + RTPHeaderExtension(const RTPHeaderExtension& other); + RTPHeaderExtension& operator=(const RTPHeaderExtension& other); -enum { kRtpCsrcSize = 15 }; // RFC 3550 page 13 + static constexpr int kAbsSendTimeFraction = 18; + + bool hasAbsoluteSendTime; + uint32_t absoluteSendTime; +}; struct RTPHeader { RTPHeader() - : markerBit(false), - payloadType(0), - sequenceNumber(0), - timestamp(0), - ssrc(0), - numCSRCs(0), - arrOfCSRCs(), - paddingLength(0), - headerLength(0){}; + : version_(kRtpVersion), + has_padding_(false), + has_extension_(false), + csrc_count_(0), + marker_(false), + payload_type_(0), + sequence_number_(1), + timestamp_(0), + ssrc_(0), + csrcs_(), + padding_len(0), + header_len(0){}; + RTPHeader(const RTPHeader& other) = default; RTPHeader& operator=(const RTPHeader& other) = default; - bool markerBit; - uint8_t payloadType; - uint16_t sequenceNumber; - uint32_t timestamp; - uint32_t ssrc; - uint8_t numCSRCs; - uint32_t arrOfCSRCs[kRtpCsrcSize]; - size_t paddingLength; - size_t headerLength; + uint8_t version_ = 0; + bool has_padding_ = false; + bool has_extension_ = false; + uint8_t csrc_count_ = 0; + bool marker_ = false; + uint8_t payload_type_ = 0; + uint16_t sequence_number_ = 1; + uint64_t timestamp_ = 0; + uint32_t ssrc_ = 0; + uint32_t csrcs_[kRtpCsrcSize]; + size_t padding_len; + size_t header_len; + + RTPHeaderExtension extension; }; #endif \ No newline at end of file diff --git a/src/rtp/rtp_packet/rtp_packet.cc b/src/rtp/rtp_packet/rtp_packet.cc new file mode 100644 index 0000000..131020d --- /dev/null +++ b/src/rtp/rtp_packet/rtp_packet.cc @@ -0,0 +1,787 @@ +#include + +#include "rtp_packet.h" + +void RtpPacket::TryToDecodeRtpPacket() { + if (PAYLOAD_TYPE::H264 == PAYLOAD_TYPE(buffer_[1] & 0x7F)) { + nal_unit_type_ = NAL_UNIT_TYPE(buffer_[12] & 0x1F); + if (NAL_UNIT_TYPE::NALU == nal_unit_type_) { + DecodeH264Nalu(); + } else if (NAL_UNIT_TYPE::FU_A == nal_unit_type_) { + DecodeH264Fua(); + } + } else if (PAYLOAD_TYPE::H264_FEC_SOURCE == PAYLOAD_TYPE(buffer_[1] & 0x7F)) { + nal_unit_type_ = NAL_UNIT_TYPE::FU_A; + DecodeH264FecSource(); + } else if (PAYLOAD_TYPE::H264_FEC_REPAIR == PAYLOAD_TYPE(buffer_[1] & 0x7F)) { + DecodeH264FecRepair(); + } else if (PAYLOAD_TYPE::AV1 == PAYLOAD_TYPE(buffer_[1] & 0x7F)) { + DecodeAv1(); + } else if (PAYLOAD_TYPE::OPUS == PAYLOAD_TYPE(buffer_[1] & 0x7F)) { + DecodeOpus(); + } else if (PAYLOAD_TYPE::DATA == PAYLOAD_TYPE(buffer_[1] & 0x7F)) { + DecodeData(); + } else { + LOG_ERROR("Unknown pt: {}", (int)PAYLOAD_TYPE(buffer_[1] & 0x7F)); + } +} + +void RtpPacket::ParseRtpData() { + if (!parsed_) { + TryToDecodeRtpPacket(); + parsed_ = true; + } +} + +RtpPacket::RtpPacket() : buffer_(new uint8_t[DEFAULT_MTU]), size_(DEFAULT_MTU) { + memset(buffer_, 0, DEFAULT_MTU); + // ParseRtpData(); +} + +RtpPacket::RtpPacket(uint32_t size) : buffer_(new uint8_t[size]), size_(size) {} + +RtpPacket::RtpPacket(const uint8_t *buffer, uint32_t size) { + if (size > 0) { + buffer_ = (uint8_t *)malloc(size); + if (NULL == buffer_) { + LOG_ERROR("Malloc failed"); + } else { + memcpy(buffer_, buffer, size); + } + size_ = size; + + // TryToDecodeH264RtpPacket(buffer_); + ParseRtpData(); + } +} + +RtpPacket::RtpPacket(const RtpPacket &rtp_packet) { + if (rtp_packet.size_ > 0) { + buffer_ = (uint8_t *)malloc(rtp_packet.size_); + if (NULL == buffer_) { + LOG_ERROR("Malloc failed"); + } else { + memcpy(buffer_, rtp_packet.buffer_, rtp_packet.size_); + } + size_ = rtp_packet.size_; + + // TryToDecodeH264RtpPacket(buffer_); + ParseRtpData(); + } +} + +RtpPacket::RtpPacket(RtpPacket &&rtp_packet) + : buffer_((uint8_t *)std::move(rtp_packet.buffer_)), + size_(rtp_packet.size_) { + rtp_packet.buffer_ = nullptr; + rtp_packet.size_ = 0; + + // TryToDecodeH264RtpPacket(buffer_); + ParseRtpData(); +} + +// RtpPacket &RtpPacket::operator=(const RtpPacket &rtp_packet) { +// if (&rtp_packet != this) { +// if (buffer_) { +// delete[] buffer_; +// buffer_ = nullptr; +// } +// buffer_ = new uint8_t[rtp_packet.size_]; +// memcpy(buffer_, rtp_packet.buffer_, rtp_packet.size_); +// size_ = rtp_packet.size_; + +// // TryToDecodeH264RtpPacket(buffer_); +// } +// return *this; +// } + +RtpPacket &RtpPacket::operator=(const RtpPacket &rtp_packet) { + if (&rtp_packet != this) { + buffer_ = (uint8_t *)realloc(buffer_, rtp_packet.size_); + memcpy(buffer_, rtp_packet.buffer_, rtp_packet.size_); + size_ = rtp_packet.size_; + + // TryToDecodeH264RtpPacket(buffer_); + } + return *this; +} + +RtpPacket &RtpPacket::operator=(RtpPacket &&rtp_packet) { + if (&rtp_packet != this) { + buffer_ = std::move(rtp_packet.buffer_); + rtp_packet.buffer_ = nullptr; + size_ = rtp_packet.size_; + rtp_packet.size_ = 0; + + // TryToDecodeH264RtpPacket(buffer_); + } + return *this; +} + +RtpPacket::~RtpPacket() { + if (buffer_) { + free(buffer_); + buffer_ = nullptr; + } + size_ = 0; + + if (extension_data_) { + free(extension_data_); + extension_data_ = nullptr; + } + extension_len_ = 0; + payload_size_ = 0; +} + +bool RtpPacket::Build(const uint8_t *buffer, uint32_t size) { + if (size > 0) { + buffer_ = (uint8_t *)malloc(size); + if (NULL == buffer_) { + LOG_ERROR("Malloc failed"); + } else { + memcpy(buffer_, buffer, size); + } + size_ = size; + + // TryToDecodeH264RtpPacket(buffer_); + return true; + } + return false; +} + +const uint8_t *RtpPacket::Encode(uint8_t *payload, size_t payload_size) { + buffer_[0] = (version_ << 6) | (has_padding_ << 5) | (has_extension_ << 4) | + csrc_count_; + buffer_[1] = (marker_ << 7) | payload_type_; + buffer_[2] = (sequence_number_ >> 8) & 0xFF; + buffer_[3] = sequence_number_ & 0xFF; + buffer_[4] = (timestamp_ >> 24) & 0xFF; + buffer_[5] = (timestamp_ >> 16) & 0xFF; + buffer_[6] = (timestamp_ >> 8) & 0xFF; + buffer_[7] = timestamp_ & 0xFF; + buffer_[8] = (ssrc_ >> 24) & 0xFF; + buffer_[9] = (ssrc_ >> 16) & 0xFF; + buffer_[10] = (ssrc_ >> 8) & 0xFF; + buffer_[11] = ssrc_ & 0xFF; + + for (uint32_t index = 0; index < csrc_count_ && !csrcs_.empty(); index++) { + buffer_[12 + index] = (csrcs_[index] >> 24) & 0xFF; + buffer_[13 + index] = (csrcs_[index] >> 16) & 0xFF; + buffer_[14 + index] = (csrcs_[index] >> 8) & 0xFF; + buffer_[15 + index] = csrcs_[index] & 0xFF; + } + + uint32_t extension_offset = + csrc_count_ && !csrcs_.empty() ? csrc_count_ * 4 : 0; + if (has_extension_ && extension_data_) { + buffer_[12 + extension_offset] = extension_profile_ >> 8; + buffer_[13 + extension_offset] = extension_profile_ & 0xff; + buffer_[14 + extension_offset] = (extension_len_ >> 8) & 0xFF; + buffer_[15 + extension_offset] = extension_len_ & 0xFF; + memcpy(buffer_ + 16 + extension_offset, extension_data_, extension_len_); + } + + uint32_t payload_offset = + (has_extension_ && extension_data_ ? extension_len_ : 0) + + extension_offset; + + memcpy(buffer_ + 12 + payload_offset, payload, payload_size); + size_ = payload_size + (12 + payload_offset); + + return buffer_; +} + +const uint8_t *RtpPacket::EncodeH264Nalu(uint8_t *payload, + size_t payload_size) { + buffer_[0] = (version_ << 6) | (has_padding_ << 5) | (has_extension_ << 4) | + csrc_count_; + buffer_[1] = (marker_ << 7) | payload_type_; + buffer_[2] = (sequence_number_ >> 8) & 0xFF; + buffer_[3] = sequence_number_ & 0xFF; + buffer_[4] = (timestamp_ >> 24) & 0xFF; + buffer_[5] = (timestamp_ >> 16) & 0xFF; + buffer_[6] = (timestamp_ >> 8) & 0xFF; + buffer_[7] = timestamp_ & 0xFF; + buffer_[8] = (ssrc_ >> 24) & 0xFF; + buffer_[9] = (ssrc_ >> 16) & 0xFF; + buffer_[10] = (ssrc_ >> 8) & 0xFF; + buffer_[11] = ssrc_ & 0xFF; + + for (uint32_t index = 0; index < csrc_count_ && !csrcs_.empty(); index++) { + buffer_[12 + index] = (csrcs_[index] >> 24) & 0xFF; + buffer_[13 + index] = (csrcs_[index] >> 16) & 0xFF; + buffer_[14 + index] = (csrcs_[index] >> 8) & 0xFF; + buffer_[15 + index] = csrcs_[index] & 0xFF; + } + + uint32_t extension_offset = + csrc_count_ && !csrcs_.empty() ? csrc_count_ * 4 : 0; + if (has_extension_ && extension_data_) { + buffer_[12 + extension_offset] = extension_profile_ >> 8; + buffer_[13 + extension_offset] = extension_profile_ & 0xff; + buffer_[14 + extension_offset] = (extension_len_ >> 8) & 0xFF; + buffer_[15 + extension_offset] = extension_len_ & 0xFF; + memcpy(buffer_ + 16 + extension_offset, extension_data_, extension_len_); + } + + uint32_t payload_offset = + (has_extension_ && extension_data_ ? extension_len_ : 0) + + extension_offset; + + buffer_[12 + payload_offset] = fu_indicator_.forbidden_bit << 7 | + fu_indicator_.nal_reference_idc << 6 | + fu_indicator_.nal_unit_type; + + memcpy(buffer_ + 13 + payload_offset, payload, payload_size); + size_ = payload_size + (13 + payload_offset); + + return buffer_; +} + +const uint8_t *RtpPacket::EncodeH264Fua(uint8_t *payload, size_t payload_size) { + buffer_[0] = (version_ << 6) | (has_padding_ << 5) | (has_extension_ << 4) | + csrc_count_; + buffer_[1] = (marker_ << 7) | payload_type_; + buffer_[2] = (sequence_number_ >> 8) & 0xFF; + buffer_[3] = sequence_number_ & 0xFF; + buffer_[4] = (timestamp_ >> 24) & 0xFF; + buffer_[5] = (timestamp_ >> 16) & 0xFF; + buffer_[6] = (timestamp_ >> 8) & 0xFF; + buffer_[7] = timestamp_ & 0xFF; + buffer_[8] = (ssrc_ >> 24) & 0xFF; + buffer_[9] = (ssrc_ >> 16) & 0xFF; + buffer_[10] = (ssrc_ >> 8) & 0xFF; + buffer_[11] = ssrc_ & 0xFF; + + for (uint32_t index = 0; index < csrc_count_ && !csrcs_.empty(); index++) { + buffer_[12 + index] = (csrcs_[index] >> 24) & 0xFF; + buffer_[13 + index] = (csrcs_[index] >> 16) & 0xFF; + buffer_[14 + index] = (csrcs_[index] >> 8) & 0xFF; + buffer_[15 + index] = csrcs_[index] & 0xFF; + } + + uint32_t extension_offset = + csrc_count_ && !csrcs_.empty() ? csrc_count_ * 4 : 0; + if (has_extension_ && extension_data_) { + buffer_[12 + extension_offset] = extension_profile_ >> 8; + buffer_[13 + extension_offset] = extension_profile_ & 0xff; + buffer_[14 + extension_offset] = (extension_len_ >> 8) & 0xFF; + buffer_[15 + extension_offset] = extension_len_ & 0xFF; + memcpy(buffer_ + 16 + extension_offset, extension_data_, extension_len_); + } + + uint32_t payload_offset = + (has_extension_ && extension_data_ ? extension_len_ : 0) + + extension_offset; + + buffer_[12 + payload_offset] = fu_indicator_.forbidden_bit << 7 | + fu_indicator_.nal_reference_idc << 6 | + fu_indicator_.nal_unit_type; + + buffer_[13 + payload_offset] = fu_header_.start << 7 | fu_header_.end << 6 | + fu_header_.remain_bit << 1 | + fu_header_.nal_unit_type; + + memcpy(buffer_ + 14 + payload_offset, payload, payload_size); + size_ = payload_size + (14 + payload_offset); + + return buffer_; +} + +const uint8_t *RtpPacket::EncodeH264FecSource(uint8_t *payload, + size_t payload_size, + uint8_t fec_symbol_id, + uint8_t fec_source_symbol_num) { + buffer_[0] = (version_ << 6) | (has_padding_ << 5) | (has_extension_ << 4) | + csrc_count_; + buffer_[1] = (marker_ << 7) | payload_type_; + buffer_[2] = (sequence_number_ >> 8) & 0xFF; + buffer_[3] = sequence_number_ & 0xFF; + buffer_[4] = (timestamp_ >> 24) & 0xFF; + buffer_[5] = (timestamp_ >> 16) & 0xFF; + buffer_[6] = (timestamp_ >> 8) & 0xFF; + buffer_[7] = timestamp_ & 0xFF; + buffer_[8] = (ssrc_ >> 24) & 0xFF; + buffer_[9] = (ssrc_ >> 16) & 0xFF; + buffer_[10] = (ssrc_ >> 8) & 0xFF; + buffer_[11] = ssrc_ & 0xFF; + + for (uint32_t index = 0; index < csrc_count_ && !csrcs_.empty(); index++) { + buffer_[12 + index] = (csrcs_[index] >> 24) & 0xFF; + buffer_[13 + index] = (csrcs_[index] >> 16) & 0xFF; + buffer_[14 + index] = (csrcs_[index] >> 8) & 0xFF; + buffer_[15 + index] = csrcs_[index] & 0xFF; + } + + uint32_t extension_offset = + csrc_count_ && !csrcs_.empty() ? csrc_count_ * 4 : 0; + if (has_extension_ && extension_data_) { + buffer_[12 + extension_offset] = extension_profile_ >> 8; + buffer_[13 + extension_offset] = extension_profile_ & 0xff; + buffer_[14 + extension_offset] = (extension_len_ >> 8) & 0xFF; + buffer_[15 + extension_offset] = extension_len_ & 0xFF; + memcpy(buffer_ + 16 + extension_offset, extension_data_, extension_len_); + } + + uint32_t fec_symbol_id_offset = + (has_extension_ && extension_data_ ? extension_len_ : 0) + + extension_offset; + + buffer_[12 + fec_symbol_id_offset] = fec_symbol_id; + + uint32_t fec_source_symbol_num_offset = fec_symbol_id_offset + 1; + buffer_[12 + fec_source_symbol_num_offset] = fec_source_symbol_num; + + uint32_t payload_offset = fec_source_symbol_num_offset + 1; + + buffer_[12 + payload_offset] = fu_indicator_.forbidden_bit << 7 | + fu_indicator_.nal_reference_idc << 6 | + fu_indicator_.nal_unit_type; + + buffer_[13 + payload_offset] = fu_header_.start << 7 | fu_header_.end << 6 | + fu_header_.remain_bit << 1 | + fu_header_.nal_unit_type; + + memcpy(buffer_ + 14 + payload_offset, payload, payload_size); + size_ = payload_size + (14 + payload_offset); + + return buffer_; +} + +const uint8_t *RtpPacket::EncodeH264FecRepair(uint8_t *payload, + size_t payload_size, + uint8_t fec_symbol_id, + uint8_t fec_source_symbol_num) { + buffer_[0] = (version_ << 6) | (has_padding_ << 5) | (has_extension_ << 4) | + csrc_count_; + buffer_[1] = (marker_ << 7) | payload_type_; + buffer_[2] = (sequence_number_ >> 8) & 0xFF; + buffer_[3] = sequence_number_ & 0xFF; + buffer_[4] = (timestamp_ >> 24) & 0xFF; + buffer_[5] = (timestamp_ >> 16) & 0xFF; + buffer_[6] = (timestamp_ >> 8) & 0xFF; + buffer_[7] = timestamp_ & 0xFF; + buffer_[8] = (ssrc_ >> 24) & 0xFF; + buffer_[9] = (ssrc_ >> 16) & 0xFF; + buffer_[10] = (ssrc_ >> 8) & 0xFF; + buffer_[11] = ssrc_ & 0xFF; + + for (uint32_t index = 0; index < csrc_count_ && !csrcs_.empty(); index++) { + buffer_[12 + index] = (csrcs_[index] >> 24) & 0xFF; + buffer_[13 + index] = (csrcs_[index] >> 16) & 0xFF; + buffer_[14 + index] = (csrcs_[index] >> 8) & 0xFF; + buffer_[15 + index] = csrcs_[index] & 0xFF; + } + + uint32_t extension_offset = + csrc_count_ && !csrcs_.empty() ? csrc_count_ * 4 : 0; + if (has_extension_ && extension_data_) { + buffer_[12 + extension_offset] = extension_profile_ >> 8; + buffer_[13 + extension_offset] = extension_profile_ & 0xff; + buffer_[14 + extension_offset] = (extension_len_ >> 8) & 0xFF; + buffer_[15 + extension_offset] = extension_len_ & 0xFF; + memcpy(buffer_ + 16 + extension_offset, extension_data_, extension_len_); + } + + uint32_t fec_symbol_id_offset = + (has_extension_ && extension_data_ ? extension_len_ : 0) + + extension_offset; + + buffer_[12 + fec_symbol_id_offset] = fec_symbol_id; + + uint32_t fec_source_symbol_num_offset = fec_symbol_id_offset + 1; + buffer_[12 + fec_source_symbol_num_offset] = fec_source_symbol_num; + + uint32_t payload_offset = fec_source_symbol_num_offset + 1; + + buffer_[12 + payload_offset] = fu_indicator_.forbidden_bit << 7 | + fu_indicator_.nal_reference_idc << 6 | + fu_indicator_.nal_unit_type; + + buffer_[13 + payload_offset] = fu_header_.start << 7 | fu_header_.end << 6 | + fu_header_.remain_bit << 1 | + fu_header_.nal_unit_type; + + memcpy(buffer_ + 14 + payload_offset, payload, payload_size); + size_ = payload_size + (14 + payload_offset); + + return buffer_; +} + +const uint8_t *RtpPacket::EncodeAv1(uint8_t *payload, size_t payload_size) { + buffer_[0] = (version_ << 6) | (has_padding_ << 5) | (has_extension_ << 4) | + csrc_count_; + buffer_[1] = (marker_ << 7) | payload_type_; + buffer_[2] = (sequence_number_ >> 8) & 0xFF; + buffer_[3] = sequence_number_ & 0xFF; + buffer_[4] = (timestamp_ >> 24) & 0xFF; + buffer_[5] = (timestamp_ >> 16) & 0xFF; + buffer_[6] = (timestamp_ >> 8) & 0xFF; + buffer_[7] = timestamp_ & 0xFF; + buffer_[8] = (ssrc_ >> 24) & 0xFF; + buffer_[9] = (ssrc_ >> 16) & 0xFF; + buffer_[10] = (ssrc_ >> 8) & 0xFF; + buffer_[11] = ssrc_ & 0xFF; + + for (uint32_t index = 0; index < csrc_count_ && !csrcs_.empty(); index++) { + buffer_[12 + index] = (csrcs_[index] >> 24) & 0xFF; + buffer_[13 + index] = (csrcs_[index] >> 16) & 0xFF; + buffer_[14 + index] = (csrcs_[index] >> 8) & 0xFF; + buffer_[15 + index] = csrcs_[index] & 0xFF; + } + + uint32_t extension_offset = + csrc_count_ && !csrcs_.empty() ? csrc_count_ * 4 : 0; + if (has_extension_ && extension_data_) { + buffer_[12 + extension_offset] = extension_profile_ >> 8; + buffer_[13 + extension_offset] = extension_profile_ & 0xff; + buffer_[14 + extension_offset] = (extension_len_ >> 8) & 0xFF; + buffer_[15 + extension_offset] = extension_len_ & 0xFF; + memcpy(buffer_ + 16 + extension_offset, extension_data_, extension_len_); + } + + uint32_t aggr_header_offset = + (has_extension_ && extension_data_ ? extension_len_ : 0) + + extension_offset; + memcpy(buffer_ + 12 + aggr_header_offset, &av1_aggr_header_, 1); + + uint32_t payload_offset = aggr_header_offset; + memcpy(buffer_ + 13 + payload_offset, payload, payload_size); + size_ = payload_size + (13 + payload_offset); + return buffer_; +} + +// ---------------------------------------------------------------------------- + +size_t RtpPacket::DecodeOpus(uint8_t *payload) { + version_ = (buffer_[0] >> 6) & 0x03; + has_padding_ = (buffer_[0] >> 5) & 0x01; + has_extension_ = (buffer_[0] >> 4) & 0x01; + csrc_count_ = buffer_[0] & 0x0f; + marker_ = (buffer_[1] >> 7) & 0x01; + payload_type_ = buffer_[1] & 0x7f; + sequence_number_ = (buffer_[2] << 8) | buffer_[3]; + timestamp_ = + (buffer_[4] << 24) | (buffer_[5] << 16) | (buffer_[6] << 8) | buffer_[7]; + ssrc_ = (buffer_[8] << 24) | (buffer_[9] << 16) | (buffer_[10] << 8) | + buffer_[11]; + + for (uint32_t index = 0; index < csrc_count_; index++) { + uint32_t csrc = (buffer_[12 + index] << 24) | (buffer_[13 + index] << 16) | + (buffer_[14 + index] << 8) | buffer_[15 + index]; + csrcs_.push_back(csrc); + } + + uint32_t extension_offset = csrc_count_ * 4; + if (has_extension_) { + extension_profile_ = + (buffer_[12 + extension_offset] << 8) | buffer_[13 + extension_offset]; + extension_len_ = + (buffer_[14 + extension_offset] << 8) | buffer_[15 + extension_offset]; + + // extension_data_ = new uint8_t[extension_len_]; + // memcpy(extension_data_, buffer_ + 16 + extension_offset, + // extension_len_); + extension_data_ = buffer_ + 16 + extension_offset; + } + + uint32_t payload_offset = + (has_extension_ ? extension_len_ : 0) + extension_offset; + + payload_size_ = size_ - (12 + payload_offset); + payload_ = buffer_ + 12 + payload_offset; + if (payload) { + memcpy(payload, payload_, payload_size_); + } + + return payload_size_; +} + +size_t RtpPacket::DecodeData(uint8_t *payload) { + version_ = (buffer_[0] >> 6) & 0x03; + has_padding_ = (buffer_[0] >> 5) & 0x01; + has_extension_ = (buffer_[0] >> 4) & 0x01; + csrc_count_ = buffer_[0] & 0x0f; + marker_ = (buffer_[1] >> 7) & 0x01; + payload_type_ = buffer_[1] & 0x7f; + sequence_number_ = (buffer_[2] << 8) | buffer_[3]; + timestamp_ = + (buffer_[4] << 24) | (buffer_[5] << 16) | (buffer_[6] << 8) | buffer_[7]; + ssrc_ = (buffer_[8] << 24) | (buffer_[9] << 16) | (buffer_[10] << 8) | + buffer_[11]; + + for (uint32_t index = 0; index < csrc_count_; index++) { + uint32_t csrc = (buffer_[12 + index] << 24) | (buffer_[13 + index] << 16) | + (buffer_[14 + index] << 8) | buffer_[15 + index]; + csrcs_.push_back(csrc); + } + + uint32_t extension_offset = csrc_count_ * 4; + if (has_extension_) { + extension_profile_ = + (buffer_[12 + extension_offset] << 8) | buffer_[13 + extension_offset]; + extension_len_ = + (buffer_[14 + extension_offset] << 8) | buffer_[15 + extension_offset]; + + // extension_data_ = new uint8_t[extension_len_]; + // memcpy(extension_data_, buffer_ + 16 + extension_offset, + // extension_len_); + extension_data_ = buffer_ + 16 + extension_offset; + } + + uint32_t payload_offset = + (has_extension_ ? extension_len_ : 0) + extension_offset; + + payload_size_ = size_ - (12 + payload_offset); + payload_ = buffer_ + 12 + payload_offset; + if (payload) { + memcpy(payload, payload_, payload_size_); + } + + return payload_size_; +} + +size_t RtpPacket::DecodeH264Nalu(uint8_t *payload) { + version_ = (buffer_[0] >> 6) & 0x03; + has_padding_ = (buffer_[0] >> 5) & 0x01; + has_extension_ = (buffer_[0] >> 4) & 0x01; + csrc_count_ = buffer_[0] & 0x0f; + marker_ = (buffer_[1] >> 7) & 0x01; + payload_type_ = buffer_[1] & 0x7f; + sequence_number_ = (buffer_[2] << 8) | buffer_[3]; + timestamp_ = + (buffer_[4] << 24) | (buffer_[5] << 16) | (buffer_[6] << 8) | buffer_[7]; + ssrc_ = (buffer_[8] << 24) | (buffer_[9] << 16) | (buffer_[10] << 8) | + buffer_[11]; + + for (uint32_t index = 0; index < csrc_count_; index++) { + uint32_t csrc = (buffer_[12 + index] << 24) | (buffer_[13 + index] << 16) | + (buffer_[14 + index] << 8) | buffer_[15 + index]; + csrcs_.push_back(csrc); + } + + uint32_t extension_offset = csrc_count_ * 4; + if (has_extension_) { + extension_profile_ = + (buffer_[12 + extension_offset] << 8) | buffer_[13 + extension_offset]; + extension_len_ = + (buffer_[14 + extension_offset] << 8) | buffer_[15 + extension_offset]; + + // extension_data_ = new uint8_t[extension_len_]; + // memcpy(extension_data_, buffer_ + 16 + extension_offset, + // extension_len_); + extension_data_ = buffer_ + 16 + extension_offset; + } + + uint32_t payload_offset = + (has_extension_ ? extension_len_ : 0) + extension_offset; + + fu_indicator_.forbidden_bit = (buffer_[12 + payload_offset] >> 7) & 0x01; + fu_indicator_.nal_reference_idc = (buffer_[12 + payload_offset] >> 5) & 0x03; + fu_indicator_.nal_unit_type = buffer_[12 + payload_offset] & 0x1F; + + payload_size_ = size_ - (13 + payload_offset); + payload_ = buffer_ + 13 + payload_offset; + if (payload) { + memcpy(payload, payload_, payload_size_); + } + return payload_size_; +} + +size_t RtpPacket::DecodeH264Fua(uint8_t *payload) { + version_ = (buffer_[0] >> 6) & 0x03; + has_padding_ = (buffer_[0] >> 5) & 0x01; + has_extension_ = (buffer_[0] >> 4) & 0x01; + csrc_count_ = buffer_[0] & 0x0f; + marker_ = (buffer_[1] >> 7) & 0x01; + payload_type_ = buffer_[1] & 0x7f; + sequence_number_ = (buffer_[2] << 8) | buffer_[3]; + timestamp_ = + (buffer_[4] << 24) | (buffer_[5] << 16) | (buffer_[6] << 8) | buffer_[7]; + ssrc_ = (buffer_[8] << 24) | (buffer_[9] << 16) | (buffer_[10] << 8) | + buffer_[11]; + + for (uint32_t index = 0; index < csrc_count_; index++) { + uint32_t csrc = (buffer_[12 + index] << 24) | (buffer_[13 + index] << 16) | + (buffer_[14 + index] << 8) | buffer_[15 + index]; + csrcs_.push_back(csrc); + } + + uint32_t extension_offset = csrc_count_ * 4; + if (has_extension_) { + extension_profile_ = + (buffer_[12 + extension_offset] << 8) | buffer_[13 + extension_offset]; + extension_len_ = + (buffer_[14 + extension_offset] << 8) | buffer_[15 + extension_offset]; + + extension_data_ = buffer_ + 16 + extension_offset; + } + + uint32_t payload_offset = + (has_extension_ ? extension_len_ : 0) + extension_offset; + + fu_indicator_.forbidden_bit = (buffer_[12 + payload_offset] >> 7) & 0x01; + fu_indicator_.nal_reference_idc = (buffer_[12 + payload_offset] >> 5) & 0x03; + fu_indicator_.nal_unit_type = buffer_[12 + payload_offset] & 0x1F; + + fu_header_.start = (buffer_[13 + payload_offset] >> 7) & 0x01; + fu_header_.end = (buffer_[13 + payload_offset] >> 6) & 0x01; + fu_header_.remain_bit = (buffer_[13 + payload_offset] >> 5) & 0x01; + fu_header_.nal_unit_type = buffer_[13 + payload_offset] & 0x1F; + + payload_size_ = size_ - (14 + payload_offset); + payload_ = buffer_ + 14 + payload_offset; + if (payload) { + memcpy(payload, payload_, payload_size_); + } + return payload_size_; +} + +size_t RtpPacket::DecodeH264FecSource(uint8_t *payload) { + version_ = (buffer_[0] >> 6) & 0x03; + has_padding_ = (buffer_[0] >> 5) & 0x01; + has_extension_ = (buffer_[0] >> 4) & 0x01; + csrc_count_ = buffer_[0] & 0x0f; + marker_ = (buffer_[1] >> 7) & 0x01; + payload_type_ = buffer_[1] & 0x7f; + sequence_number_ = (buffer_[2] << 8) | buffer_[3]; + timestamp_ = + (buffer_[4] << 24) | (buffer_[5] << 16) | (buffer_[6] << 8) | buffer_[7]; + ssrc_ = (buffer_[8] << 24) | (buffer_[9] << 16) | (buffer_[10] << 8) | + buffer_[11]; + + for (uint32_t index = 0; index < csrc_count_; index++) { + uint32_t csrc = (buffer_[12 + index] << 24) | (buffer_[13 + index] << 16) | + (buffer_[14 + index] << 8) | buffer_[15 + index]; + csrcs_.push_back(csrc); + } + + uint32_t extension_offset = csrc_count_ * 4; + if (has_extension_) { + extension_profile_ = + (buffer_[12 + extension_offset] << 8) | buffer_[13 + extension_offset]; + extension_len_ = + (buffer_[14 + extension_offset] << 8) | buffer_[15 + extension_offset]; + + extension_data_ = buffer_ + 16 + extension_offset; + } + + uint32_t fec_symbol_id_offset = + extension_offset + (has_extension_ ? extension_len_ : 0); + fec_symbol_id_ = buffer_[12 + fec_symbol_id_offset]; + + uint32_t fec_source_symbol_num_offset = fec_symbol_id_offset + 1; + fec_source_symbol_num_ = buffer_[12 + fec_source_symbol_num_offset]; + + uint32_t payload_offset = fec_source_symbol_num_offset + 1; + + fu_indicator_.forbidden_bit = (buffer_[12 + payload_offset] >> 7) & 0x01; + fu_indicator_.nal_reference_idc = (buffer_[12 + payload_offset] >> 5) & 0x03; + fu_indicator_.nal_unit_type = buffer_[12 + payload_offset] & 0x1F; + + fu_header_.start = (buffer_[13 + payload_offset] >> 7) & 0x01; + fu_header_.end = (buffer_[13 + payload_offset] >> 6) & 0x01; + fu_header_.remain_bit = (buffer_[13 + payload_offset] >> 5) & 0x01; + fu_header_.nal_unit_type = buffer_[13 + payload_offset] & 0x1F; + + payload_size_ = size_ - (14 + payload_offset); + payload_ = buffer_ + 14 + payload_offset; + if (payload) { + memcpy(payload, payload_, payload_size_); + } + return payload_size_; +} + +size_t RtpPacket::DecodeH264FecRepair(uint8_t *payload) { + version_ = (buffer_[0] >> 6) & 0x03; + has_padding_ = (buffer_[0] >> 5) & 0x01; + has_extension_ = (buffer_[0] >> 4) & 0x01; + csrc_count_ = buffer_[0] & 0x0f; + marker_ = (buffer_[1] >> 7) & 0x01; + payload_type_ = buffer_[1] & 0x7f; + sequence_number_ = (buffer_[2] << 8) | buffer_[3]; + timestamp_ = + (buffer_[4] << 24) | (buffer_[5] << 16) | (buffer_[6] << 8) | buffer_[7]; + ssrc_ = (buffer_[8] << 24) | (buffer_[9] << 16) | (buffer_[10] << 8) | + buffer_[11]; + + for (uint32_t index = 0; index < csrc_count_; index++) { + uint32_t csrc = (buffer_[12 + index] << 24) | (buffer_[13 + index] << 16) | + (buffer_[14 + index] << 8) | buffer_[15 + index]; + csrcs_.push_back(csrc); + } + + uint32_t extension_offset = csrc_count_ * 4; + if (has_extension_) { + extension_profile_ = + (buffer_[12 + extension_offset] << 8) | buffer_[13 + extension_offset]; + extension_len_ = + (buffer_[14 + extension_offset] << 8) | buffer_[15 + extension_offset]; + + extension_data_ = buffer_ + 16 + extension_offset; + } + + uint32_t fec_symbol_id_offset = + extension_offset + (has_extension_ ? extension_len_ : 0); + fec_symbol_id_ = buffer_[12 + fec_symbol_id_offset]; + + uint32_t fec_source_symbol_num_offset = fec_symbol_id_offset + 1; + fec_source_symbol_num_ = buffer_[12 + fec_source_symbol_num_offset]; + + uint32_t payload_offset = fec_source_symbol_num_offset + 1; + + payload_size_ = size_ - (14 + payload_offset); + payload_ = buffer_ + 14 + payload_offset; + if (payload) { + memcpy(payload, payload_, payload_size_); + } + return payload_size_; +} + +size_t RtpPacket::DecodeAv1(uint8_t *payload) { + version_ = (buffer_[0] >> 6) & 0x03; + has_padding_ = (buffer_[0] >> 5) & 0x01; + has_extension_ = (buffer_[0] >> 4) & 0x01; + csrc_count_ = buffer_[0] & 0x0f; + marker_ = (buffer_[1] >> 7) & 0x01; + payload_type_ = buffer_[1] & 0x7f; + sequence_number_ = (buffer_[2] << 8) | buffer_[3]; + timestamp_ = + (buffer_[4] << 24) | (buffer_[5] << 16) | (buffer_[6] << 8) | buffer_[7]; + ssrc_ = (buffer_[8] << 24) | (buffer_[9] << 16) | (buffer_[10] << 8) | + buffer_[11]; + + for (uint32_t index = 0; index < csrc_count_; index++) { + uint32_t csrc = (buffer_[12 + index] << 24) | (buffer_[13 + index] << 16) | + (buffer_[14 + index] << 8) | buffer_[15 + index]; + csrcs_.push_back(csrc); + } + + uint32_t extension_offset = csrc_count_ * 4; + if (has_extension_) { + extension_profile_ = + (buffer_[12 + extension_offset] << 8) | buffer_[13 + extension_offset]; + extension_len_ = + (buffer_[14 + extension_offset] << 8) | buffer_[15 + extension_offset]; + + // extension_data_ = new uint8_t[extension_len_]; + // memcpy(extension_data_, buffer_ + 16 + extension_offset, + // extension_len_); + extension_data_ = buffer_ + 16 + extension_offset; + } + + uint32_t aggr_header_offset = + (has_extension_ ? extension_len_ : 0) + extension_offset; + + av1_aggr_header_ = buffer_[12 + aggr_header_offset]; + + uint32_t payload_offset = aggr_header_offset; + + payload_size_ = size_ - (13 + payload_offset); + payload_ = buffer_ + 13 + payload_offset; + if (payload) { + memcpy(payload, payload_, payload_size_); + } + + return payload_size_; +} \ No newline at end of file diff --git a/src/rtp/rtp_packet/rtp_packet.cpp b/src/rtp/rtp_packet/rtp_packet.cpp index 81a0ab8..3f109c4 100644 --- a/src/rtp/rtp_packet/rtp_packet.cpp +++ b/src/rtp/rtp_packet/rtp_packet.cpp @@ -2,792 +2,133 @@ #include -void RtpPacket::TryToDecodeRtpPacket() { - if (PAYLOAD_TYPE::H264 == PAYLOAD_TYPE(buffer_[1] & 0x7F)) { - nal_unit_type_ = NAL_UNIT_TYPE(buffer_[12] & 0x1F); - if (NAL_UNIT_TYPE::NALU == nal_unit_type_) { - DecodeH264Nalu(); - } else if (NAL_UNIT_TYPE::FU_A == nal_unit_type_) { - DecodeH264Fua(); - } - } else if (PAYLOAD_TYPE::H264_FEC_SOURCE == PAYLOAD_TYPE(buffer_[1] & 0x7F)) { - nal_unit_type_ = NAL_UNIT_TYPE::FU_A; - DecodeH264FecSource(); - } else if (PAYLOAD_TYPE::H264_FEC_REPAIR == PAYLOAD_TYPE(buffer_[1] & 0x7F)) { - DecodeH264FecRepair(); - } else if (PAYLOAD_TYPE::AV1 == PAYLOAD_TYPE(buffer_[1] & 0x7F)) { - DecodeAv1(); - } else if (PAYLOAD_TYPE::OPUS == PAYLOAD_TYPE(buffer_[1] & 0x7F)) { - DecodeOpus(); - } else if (PAYLOAD_TYPE::DATA == PAYLOAD_TYPE(buffer_[1] & 0x7F)) { - DecodeData(); - } else { - LOG_ERROR("Unknown pt: {}", (int)PAYLOAD_TYPE(buffer_[1] & 0x7F)); - } -} +RtpPacket::RtpPacket() {} -void RtpPacket::ParseRtpData() { - if (!parsed_) { - TryToDecodeRtpPacket(); - parsed_ = true; - } -} +RtpPacket::RtpPacket(const RtpPacket &rtp_packet) = default; -RtpPacket::RtpPacket() : buffer_(new uint8_t[DEFAULT_MTU]), size_(DEFAULT_MTU) { - memset(buffer_, 0, DEFAULT_MTU); - // ParseRtpData(); -} +RtpPacket::RtpPacket(RtpPacket &&rtp_packet) = default; -RtpPacket::RtpPacket(uint32_t size) : buffer_(new uint8_t[size]), size_(size) {} +RtpPacket &RtpPacket::operator=(const RtpPacket &rtp_packet) = default; -RtpPacket::RtpPacket(const uint8_t *buffer, uint32_t size) { - if (size > 0) { - buffer_ = (uint8_t *)malloc(size); - if (NULL == buffer_) { - LOG_ERROR("Malloc failed"); - } else { - memcpy(buffer_, buffer, size); - } - size_ = size; +RtpPacket &RtpPacket::operator=(RtpPacket &&rtp_packet) = default; - // TryToDecodeH264RtpPacket(buffer_); - ParseRtpData(); - } -} - -RtpPacket::RtpPacket(const RtpPacket &rtp_packet) { - if (rtp_packet.size_ > 0) { - buffer_ = (uint8_t *)malloc(rtp_packet.size_); - if (NULL == buffer_) { - LOG_ERROR("Malloc failed"); - } else { - memcpy(buffer_, rtp_packet.buffer_, rtp_packet.size_); - } - size_ = rtp_packet.size_; - - // TryToDecodeH264RtpPacket(buffer_); - ParseRtpData(); - } -} - -RtpPacket::RtpPacket(RtpPacket &&rtp_packet) - : buffer_((uint8_t *)std::move(rtp_packet.buffer_)), - size_(rtp_packet.size_) { - rtp_packet.buffer_ = nullptr; - rtp_packet.size_ = 0; - - // TryToDecodeH264RtpPacket(buffer_); - ParseRtpData(); -} - -// RtpPacket &RtpPacket::operator=(const RtpPacket &rtp_packet) { -// if (&rtp_packet != this) { -// if (buffer_) { -// delete[] buffer_; -// buffer_ = nullptr; -// } -// buffer_ = new uint8_t[rtp_packet.size_]; -// memcpy(buffer_, rtp_packet.buffer_, rtp_packet.size_); -// size_ = rtp_packet.size_; - -// // TryToDecodeH264RtpPacket(buffer_); -// } -// return *this; -// } - -RtpPacket &RtpPacket::operator=(const RtpPacket &rtp_packet) { - if (&rtp_packet != this) { - buffer_ = (uint8_t *)realloc(buffer_, rtp_packet.size_); - memcpy(buffer_, rtp_packet.buffer_, rtp_packet.size_); - size_ = rtp_packet.size_; - - // TryToDecodeH264RtpPacket(buffer_); - } - return *this; -} - -RtpPacket &RtpPacket::operator=(RtpPacket &&rtp_packet) { - if (&rtp_packet != this) { - buffer_ = std::move(rtp_packet.buffer_); - rtp_packet.buffer_ = nullptr; - size_ = rtp_packet.size_; - rtp_packet.size_ = 0; - - // TryToDecodeH264RtpPacket(buffer_); - } - return *this; -} - -RtpPacket::~RtpPacket() { - if (buffer_) { - free(buffer_); - buffer_ = nullptr; - } - size_ = 0; - - if (extension_data_) { - free(extension_data_); - extension_data_ = nullptr; - } - extension_len_ = 0; - payload_size_ = 0; -} +RtpPacket::~RtpPacket() = default; bool RtpPacket::Build(const uint8_t *buffer, uint32_t size) { if (size > 0) { - buffer_ = (uint8_t *)malloc(size); - if (NULL == buffer_) { - LOG_ERROR("Malloc failed"); - } else { - memcpy(buffer_, buffer, size); - } + buffer_.SetData(buffer, size); size_ = size; - - // TryToDecodeH264RtpPacket(buffer_); return true; } return false; } -const uint8_t *RtpPacket::Encode(uint8_t *payload, size_t payload_size) { - buffer_[0] = (version_ << 6) | (has_padding_ << 5) | (has_extension_ << 4) | - total_csrc_number_; - buffer_[1] = (marker_ << 7) | payload_type_; - buffer_[2] = (sequence_number_ >> 8) & 0xFF; - buffer_[3] = sequence_number_ & 0xFF; - buffer_[4] = (timestamp_ >> 24) & 0xFF; - buffer_[5] = (timestamp_ >> 16) & 0xFF; - buffer_[6] = (timestamp_ >> 8) & 0xFF; - buffer_[7] = timestamp_ & 0xFF; - buffer_[8] = (ssrc_ >> 24) & 0xFF; - buffer_[9] = (ssrc_ >> 16) & 0xFF; - buffer_[10] = (ssrc_ >> 8) & 0xFF; - buffer_[11] = ssrc_ & 0xFF; - - for (uint32_t index = 0; index < total_csrc_number_ && !csrcs_.empty(); - index++) { - buffer_[12 + index] = (csrcs_[index] >> 24) & 0xFF; - buffer_[13 + index] = (csrcs_[index] >> 16) & 0xFF; - buffer_[14 + index] = (csrcs_[index] >> 8) & 0xFF; - buffer_[15 + index] = csrcs_[index] & 0xFF; +bool RtpPacket::Parse(const uint8_t *buffer, uint32_t size) { + if (size < kFixedHeaderSize) { + LOG_WARN("RtpPacket::Parse: size is too small"); + return false; } - uint32_t extension_offset = - total_csrc_number_ && !csrcs_.empty() ? total_csrc_number_ * 4 : 0; - if (has_extension_ && extension_data_) { - buffer_[12 + extension_offset] = extension_profile_ >> 8; - buffer_[13 + extension_offset] = extension_profile_ & 0xff; - buffer_[14 + extension_offset] = (extension_len_ >> 8) & 0xFF; - buffer_[15 + extension_offset] = extension_len_ & 0xFF; - memcpy(buffer_ + 16 + extension_offset, extension_data_, extension_len_); + // 1st byte + version_ = (buffer_[payload_offset_] >> 6) & 0x03; + if (version_ != kRtpVersion) { + LOG_WARN("RtpPacket::Parse: version is not qual to kRtpVersion"); + return false; + } + has_padding_ = (buffer_[payload_offset_] >> 5) & 0x01; + has_extension_ = (buffer_[payload_offset_] >> 4) & 0x01; + csrc_count_ = buffer_[payload_offset_] & 0x0f; + if (csrc_count_ > kMaxRtpCsrcSize) { + LOG_WARN("RtpPacket::Parse: csrc count is too large"); + return false; } - uint32_t payload_offset = - (has_extension_ && extension_data_ ? extension_len_ : 0) + - extension_offset; + // 2nd byte + marker_ = (buffer_[payload_offset_] >> 7) & 0x01; + payload_type_ = buffer_[payload_offset_] & 0x7f; - memcpy(buffer_ + 12 + payload_offset, payload, payload_size); - size_ = payload_size + (12 + payload_offset); + // 3rd byte and 4th byte + sequence_number_ = + (buffer_[payload_offset_] << 8) | buffer_[payload_offset_ + 1]; - return buffer_; -} - -const uint8_t *RtpPacket::EncodeH264Nalu(uint8_t *payload, - size_t payload_size) { - buffer_[0] = (version_ << 6) | (has_padding_ << 5) | (has_extension_ << 4) | - total_csrc_number_; - buffer_[1] = (marker_ << 7) | payload_type_; - buffer_[2] = (sequence_number_ >> 8) & 0xFF; - buffer_[3] = sequence_number_ & 0xFF; - buffer_[4] = (timestamp_ >> 24) & 0xFF; - buffer_[5] = (timestamp_ >> 16) & 0xFF; - buffer_[6] = (timestamp_ >> 8) & 0xFF; - buffer_[7] = timestamp_ & 0xFF; - buffer_[8] = (ssrc_ >> 24) & 0xFF; - buffer_[9] = (ssrc_ >> 16) & 0xFF; - buffer_[10] = (ssrc_ >> 8) & 0xFF; - buffer_[11] = ssrc_ & 0xFF; - - for (uint32_t index = 0; index < total_csrc_number_ && !csrcs_.empty(); - index++) { - buffer_[12 + index] = (csrcs_[index] >> 24) & 0xFF; - buffer_[13 + index] = (csrcs_[index] >> 16) & 0xFF; - buffer_[14 + index] = (csrcs_[index] >> 8) & 0xFF; - buffer_[15 + index] = csrcs_[index] & 0xFF; - } - - uint32_t extension_offset = - total_csrc_number_ && !csrcs_.empty() ? total_csrc_number_ * 4 : 0; - if (has_extension_ && extension_data_) { - buffer_[12 + extension_offset] = extension_profile_ >> 8; - buffer_[13 + extension_offset] = extension_profile_ & 0xff; - buffer_[14 + extension_offset] = (extension_len_ >> 8) & 0xFF; - buffer_[15 + extension_offset] = extension_len_ & 0xFF; - memcpy(buffer_ + 16 + extension_offset, extension_data_, extension_len_); - } - - uint32_t payload_offset = - (has_extension_ && extension_data_ ? extension_len_ : 0) + - extension_offset; - - buffer_[12 + payload_offset] = fu_indicator_.forbidden_bit << 7 | - fu_indicator_.nal_reference_idc << 6 | - fu_indicator_.nal_unit_type; - - memcpy(buffer_ + 13 + payload_offset, payload, payload_size); - size_ = payload_size + (13 + payload_offset); - - return buffer_; -} - -const uint8_t *RtpPacket::EncodeH264Fua(uint8_t *payload, size_t payload_size) { - buffer_[0] = (version_ << 6) | (has_padding_ << 5) | (has_extension_ << 4) | - total_csrc_number_; - buffer_[1] = (marker_ << 7) | payload_type_; - buffer_[2] = (sequence_number_ >> 8) & 0xFF; - buffer_[3] = sequence_number_ & 0xFF; - buffer_[4] = (timestamp_ >> 24) & 0xFF; - buffer_[5] = (timestamp_ >> 16) & 0xFF; - buffer_[6] = (timestamp_ >> 8) & 0xFF; - buffer_[7] = timestamp_ & 0xFF; - buffer_[8] = (ssrc_ >> 24) & 0xFF; - buffer_[9] = (ssrc_ >> 16) & 0xFF; - buffer_[10] = (ssrc_ >> 8) & 0xFF; - buffer_[11] = ssrc_ & 0xFF; - - for (uint32_t index = 0; index < total_csrc_number_ && !csrcs_.empty(); - index++) { - buffer_[12 + index] = (csrcs_[index] >> 24) & 0xFF; - buffer_[13 + index] = (csrcs_[index] >> 16) & 0xFF; - buffer_[14 + index] = (csrcs_[index] >> 8) & 0xFF; - buffer_[15 + index] = csrcs_[index] & 0xFF; - } - - uint32_t extension_offset = - total_csrc_number_ && !csrcs_.empty() ? total_csrc_number_ * 4 : 0; - if (has_extension_ && extension_data_) { - buffer_[12 + extension_offset] = extension_profile_ >> 8; - buffer_[13 + extension_offset] = extension_profile_ & 0xff; - buffer_[14 + extension_offset] = (extension_len_ >> 8) & 0xFF; - buffer_[15 + extension_offset] = extension_len_ & 0xFF; - memcpy(buffer_ + 16 + extension_offset, extension_data_, extension_len_); - } - - uint32_t payload_offset = - (has_extension_ && extension_data_ ? extension_len_ : 0) + - extension_offset; - - buffer_[12 + payload_offset] = fu_indicator_.forbidden_bit << 7 | - fu_indicator_.nal_reference_idc << 6 | - fu_indicator_.nal_unit_type; - - buffer_[13 + payload_offset] = fu_header_.start << 7 | fu_header_.end << 6 | - fu_header_.remain_bit << 1 | - fu_header_.nal_unit_type; - - memcpy(buffer_ + 14 + payload_offset, payload, payload_size); - size_ = payload_size + (14 + payload_offset); - - return buffer_; -} - -const uint8_t *RtpPacket::EncodeH264FecSource(uint8_t *payload, - size_t payload_size, - uint8_t fec_symbol_id, - uint8_t fec_source_symbol_num) { - buffer_[0] = (version_ << 6) | (has_padding_ << 5) | (has_extension_ << 4) | - total_csrc_number_; - buffer_[1] = (marker_ << 7) | payload_type_; - buffer_[2] = (sequence_number_ >> 8) & 0xFF; - buffer_[3] = sequence_number_ & 0xFF; - buffer_[4] = (timestamp_ >> 24) & 0xFF; - buffer_[5] = (timestamp_ >> 16) & 0xFF; - buffer_[6] = (timestamp_ >> 8) & 0xFF; - buffer_[7] = timestamp_ & 0xFF; - buffer_[8] = (ssrc_ >> 24) & 0xFF; - buffer_[9] = (ssrc_ >> 16) & 0xFF; - buffer_[10] = (ssrc_ >> 8) & 0xFF; - buffer_[11] = ssrc_ & 0xFF; - - for (uint32_t index = 0; index < total_csrc_number_ && !csrcs_.empty(); - index++) { - buffer_[12 + index] = (csrcs_[index] >> 24) & 0xFF; - buffer_[13 + index] = (csrcs_[index] >> 16) & 0xFF; - buffer_[14 + index] = (csrcs_[index] >> 8) & 0xFF; - buffer_[15 + index] = csrcs_[index] & 0xFF; - } - - uint32_t extension_offset = - total_csrc_number_ && !csrcs_.empty() ? total_csrc_number_ * 4 : 0; - if (has_extension_ && extension_data_) { - buffer_[12 + extension_offset] = extension_profile_ >> 8; - buffer_[13 + extension_offset] = extension_profile_ & 0xff; - buffer_[14 + extension_offset] = (extension_len_ >> 8) & 0xFF; - buffer_[15 + extension_offset] = extension_len_ & 0xFF; - memcpy(buffer_ + 16 + extension_offset, extension_data_, extension_len_); - } - - uint32_t fec_symbol_id_offset = - (has_extension_ && extension_data_ ? extension_len_ : 0) + - extension_offset; - - buffer_[12 + fec_symbol_id_offset] = fec_symbol_id; - - uint32_t fec_source_symbol_num_offset = fec_symbol_id_offset + 1; - buffer_[12 + fec_source_symbol_num_offset] = fec_source_symbol_num; - - uint32_t payload_offset = fec_source_symbol_num_offset + 1; - - buffer_[12 + payload_offset] = fu_indicator_.forbidden_bit << 7 | - fu_indicator_.nal_reference_idc << 6 | - fu_indicator_.nal_unit_type; - - buffer_[13 + payload_offset] = fu_header_.start << 7 | fu_header_.end << 6 | - fu_header_.remain_bit << 1 | - fu_header_.nal_unit_type; - - memcpy(buffer_ + 14 + payload_offset, payload, payload_size); - size_ = payload_size + (14 + payload_offset); - - return buffer_; -} - -const uint8_t *RtpPacket::EncodeH264FecRepair(uint8_t *payload, - size_t payload_size, - uint8_t fec_symbol_id, - uint8_t fec_source_symbol_num) { - buffer_[0] = (version_ << 6) | (has_padding_ << 5) | (has_extension_ << 4) | - total_csrc_number_; - buffer_[1] = (marker_ << 7) | payload_type_; - buffer_[2] = (sequence_number_ >> 8) & 0xFF; - buffer_[3] = sequence_number_ & 0xFF; - buffer_[4] = (timestamp_ >> 24) & 0xFF; - buffer_[5] = (timestamp_ >> 16) & 0xFF; - buffer_[6] = (timestamp_ >> 8) & 0xFF; - buffer_[7] = timestamp_ & 0xFF; - buffer_[8] = (ssrc_ >> 24) & 0xFF; - buffer_[9] = (ssrc_ >> 16) & 0xFF; - buffer_[10] = (ssrc_ >> 8) & 0xFF; - buffer_[11] = ssrc_ & 0xFF; - - for (uint32_t index = 0; index < total_csrc_number_ && !csrcs_.empty(); - index++) { - buffer_[12 + index] = (csrcs_[index] >> 24) & 0xFF; - buffer_[13 + index] = (csrcs_[index] >> 16) & 0xFF; - buffer_[14 + index] = (csrcs_[index] >> 8) & 0xFF; - buffer_[15 + index] = csrcs_[index] & 0xFF; - } - - uint32_t extension_offset = - total_csrc_number_ && !csrcs_.empty() ? total_csrc_number_ * 4 : 0; - if (has_extension_ && extension_data_) { - buffer_[12 + extension_offset] = extension_profile_ >> 8; - buffer_[13 + extension_offset] = extension_profile_ & 0xff; - buffer_[14 + extension_offset] = (extension_len_ >> 8) & 0xFF; - buffer_[15 + extension_offset] = extension_len_ & 0xFF; - memcpy(buffer_ + 16 + extension_offset, extension_data_, extension_len_); - } - - uint32_t fec_symbol_id_offset = - (has_extension_ && extension_data_ ? extension_len_ : 0) + - extension_offset; - - buffer_[12 + fec_symbol_id_offset] = fec_symbol_id; - - uint32_t fec_source_symbol_num_offset = fec_symbol_id_offset + 1; - buffer_[12 + fec_source_symbol_num_offset] = fec_source_symbol_num; - - uint32_t payload_offset = fec_source_symbol_num_offset + 1; - - buffer_[12 + payload_offset] = fu_indicator_.forbidden_bit << 7 | - fu_indicator_.nal_reference_idc << 6 | - fu_indicator_.nal_unit_type; - - buffer_[13 + payload_offset] = fu_header_.start << 7 | fu_header_.end << 6 | - fu_header_.remain_bit << 1 | - fu_header_.nal_unit_type; - - memcpy(buffer_ + 14 + payload_offset, payload, payload_size); - size_ = payload_size + (14 + payload_offset); - - return buffer_; -} - -const uint8_t *RtpPacket::EncodeAv1(uint8_t *payload, size_t payload_size) { - buffer_[0] = (version_ << 6) | (has_padding_ << 5) | (has_extension_ << 4) | - total_csrc_number_; - buffer_[1] = (marker_ << 7) | payload_type_; - buffer_[2] = (sequence_number_ >> 8) & 0xFF; - buffer_[3] = sequence_number_ & 0xFF; - buffer_[4] = (timestamp_ >> 24) & 0xFF; - buffer_[5] = (timestamp_ >> 16) & 0xFF; - buffer_[6] = (timestamp_ >> 8) & 0xFF; - buffer_[7] = timestamp_ & 0xFF; - buffer_[8] = (ssrc_ >> 24) & 0xFF; - buffer_[9] = (ssrc_ >> 16) & 0xFF; - buffer_[10] = (ssrc_ >> 8) & 0xFF; - buffer_[11] = ssrc_ & 0xFF; - - for (uint32_t index = 0; index < total_csrc_number_ && !csrcs_.empty(); - index++) { - buffer_[12 + index] = (csrcs_[index] >> 24) & 0xFF; - buffer_[13 + index] = (csrcs_[index] >> 16) & 0xFF; - buffer_[14 + index] = (csrcs_[index] >> 8) & 0xFF; - buffer_[15 + index] = csrcs_[index] & 0xFF; - } - - uint32_t extension_offset = - total_csrc_number_ && !csrcs_.empty() ? total_csrc_number_ * 4 : 0; - if (has_extension_ && extension_data_) { - buffer_[12 + extension_offset] = extension_profile_ >> 8; - buffer_[13 + extension_offset] = extension_profile_ & 0xff; - buffer_[14 + extension_offset] = (extension_len_ >> 8) & 0xFF; - buffer_[15 + extension_offset] = extension_len_ & 0xFF; - memcpy(buffer_ + 16 + extension_offset, extension_data_, extension_len_); - } - - uint32_t aggr_header_offset = - (has_extension_ && extension_data_ ? extension_len_ : 0) + - extension_offset; - memcpy(buffer_ + 12 + aggr_header_offset, &av1_aggr_header_, 1); - - uint32_t payload_offset = aggr_header_offset; - memcpy(buffer_ + 13 + payload_offset, payload, payload_size); - size_ = payload_size + (13 + payload_offset); - return buffer_; -} - -// ---------------------------------------------------------------------------- - -size_t RtpPacket::DecodeOpus(uint8_t *payload) { - version_ = (buffer_[0] >> 6) & 0x03; - has_padding_ = (buffer_[0] >> 5) & 0x01; - has_extension_ = (buffer_[0] >> 4) & 0x01; - total_csrc_number_ = buffer_[0] & 0x0f; - marker_ = (buffer_[1] >> 7) & 0x01; - payload_type_ = buffer_[1] & 0x7f; - sequence_number_ = (buffer_[2] << 8) | buffer_[3]; + // 5th byte to 8th byte timestamp_ = - (buffer_[4] << 24) | (buffer_[5] << 16) | (buffer_[6] << 8) | buffer_[7]; - ssrc_ = (buffer_[8] << 24) | (buffer_[9] << 16) | (buffer_[10] << 8) | - buffer_[11]; + (buffer_[payload_offset_] << 24) | (buffer_[payload_offset_ + 1] << 16) | + (buffer_[payload_offset_ + 2] << 8) | buffer_[payload_offset_ + 3]; - for (uint32_t index = 0; index < total_csrc_number_; index++) { - uint32_t csrc = (buffer_[12 + index] << 24) | (buffer_[13 + index] << 16) | - (buffer_[14 + index] << 8) | buffer_[15 + index]; + // 9th byte to 12th byte + ssrc_ = (buffer_[payload_offset_] << 24) | + (buffer_[payload_offset_ + 1] << 16) | + (buffer_[payload_offset_ + 2] << 8) | buffer_[payload_offset_ + 3]; + + payload_offset_ = kFixedHeaderSize; + + if (kFixedHeaderSize + csrc_count_ * 4 > size) { + LOG_WARN("RtpPacket::Parse: csrc count is too large"); + return false; + } + // csrc + for (uint32_t csrc_index = 0; i < csrc_count_; i++) { + uint32_t csrc = (buffer_[payload_offset_ + csrc_index * 4] << 24) | + (buffer_[payload_offset_ + 1 + csrc_index * 4] << 16) | + (buffer_[payload_offset_ + 2 + csrc_index * 4] << 8) | + buffer_[payload_offset_ + 3 + csrc_index * 4]; csrcs_.push_back(csrc); } - uint32_t extension_offset = total_csrc_number_ * 4; + payload_offset_ = kFixedHeaderSize + csrc_count_ * 4; + if (payload_offset_ > size) { + LOG_WARN("RtpPacket::Parse: payload offset is too large"); + return false; + } + + // extensions if (has_extension_) { + if (payload_offset_ + 4 > size) { + LOG_WARN("RtpPacket::Parse: extension profile is too large"); + return false; + } extension_profile_ = - (buffer_[12 + extension_offset] << 8) | buffer_[13 + extension_offset]; + (buffer_[payload_offset_] << 8) | buffer_[payload_offset_ + 1]; extension_len_ = - (buffer_[14 + extension_offset] << 8) | buffer_[15 + extension_offset]; + (buffer_[payload_offset_ + 2] << 8) | buffer_[payload_offset_ + 3]; - // extension_data_ = new uint8_t[extension_len_]; - // memcpy(extension_data_, buffer_ + 16 + extension_offset, - // extension_len_); - extension_data_ = buffer_ + 16 + extension_offset; + if (payload_offset_ + 4 + extension_len_ > size) { + LOG_WARN("RtpPacket::Parse: extension len is too large"); + return false; + } + + size_t offset = payload_offset_ + 4; + while (offset < size && extension_len_ > 0) { + uint8_t id = buffer_[offset] >> 4; + uint8_t len = (buffer_[offset] & 0x0F) + 1; + if (offset + 1 + len > size) { + break; + } + extensions_.push_back( + {id, std::vector(buffer_ + offset + 1, + buffer_ + offset + 1 + len)}); + offset += 1 + len; + } + payload_offset_ += (4 + extension_len_); } - uint32_t payload_offset = - (has_extension_ ? extension_len_ : 0) + extension_offset; - - payload_size_ = size_ - (12 + payload_offset); - payload_ = buffer_ + 12 + payload_offset; - if (payload) { - memcpy(payload, payload_, payload_size_); + if (has_padding_ && payload_offset_ < size) { + padding_size_ = buffer[size - 1]; + if (padding_size_ == 0) { + LOG_WARN("Padding was set, but padding size is zero"); + return false; + } + } else { + padding_size_ = 0; } - return payload_size_; -} - -size_t RtpPacket::DecodeData(uint8_t *payload) { - version_ = (buffer_[0] >> 6) & 0x03; - has_padding_ = (buffer_[0] >> 5) & 0x01; - has_extension_ = (buffer_[0] >> 4) & 0x01; - total_csrc_number_ = buffer_[0] & 0x0f; - marker_ = (buffer_[1] >> 7) & 0x01; - payload_type_ = buffer_[1] & 0x7f; - sequence_number_ = (buffer_[2] << 8) | buffer_[3]; - timestamp_ = - (buffer_[4] << 24) | (buffer_[5] << 16) | (buffer_[6] << 8) | buffer_[7]; - ssrc_ = (buffer_[8] << 24) | (buffer_[9] << 16) | (buffer_[10] << 8) | - buffer_[11]; - - for (uint32_t index = 0; index < total_csrc_number_; index++) { - uint32_t csrc = (buffer_[12 + index] << 24) | (buffer_[13 + index] << 16) | - (buffer_[14 + index] << 8) | buffer_[15 + index]; - csrcs_.push_back(csrc); + // payload + if (payload_offset_ + padding_size_ > size) { + LOG_WARN("RtpPacket::Parse: payload size is too large"); + return false; } + payload_size_ = size - payload_offset_ - padding_size_; - uint32_t extension_offset = total_csrc_number_ * 4; - if (has_extension_) { - extension_profile_ = - (buffer_[12 + extension_offset] << 8) | buffer_[13 + extension_offset]; - extension_len_ = - (buffer_[14 + extension_offset] << 8) | buffer_[15 + extension_offset]; - - // extension_data_ = new uint8_t[extension_len_]; - // memcpy(extension_data_, buffer_ + 16 + extension_offset, - // extension_len_); - extension_data_ = buffer_ + 16 + extension_offset; - } - - uint32_t payload_offset = - (has_extension_ ? extension_len_ : 0) + extension_offset; - - payload_size_ = size_ - (12 + payload_offset); - payload_ = buffer_ + 12 + payload_offset; - if (payload) { - memcpy(payload, payload_, payload_size_); - } - - return payload_size_; -} - -size_t RtpPacket::DecodeH264Nalu(uint8_t *payload) { - version_ = (buffer_[0] >> 6) & 0x03; - has_padding_ = (buffer_[0] >> 5) & 0x01; - has_extension_ = (buffer_[0] >> 4) & 0x01; - total_csrc_number_ = buffer_[0] & 0x0f; - marker_ = (buffer_[1] >> 7) & 0x01; - payload_type_ = buffer_[1] & 0x7f; - sequence_number_ = (buffer_[2] << 8) | buffer_[3]; - timestamp_ = - (buffer_[4] << 24) | (buffer_[5] << 16) | (buffer_[6] << 8) | buffer_[7]; - ssrc_ = (buffer_[8] << 24) | (buffer_[9] << 16) | (buffer_[10] << 8) | - buffer_[11]; - - for (uint32_t index = 0; index < total_csrc_number_; index++) { - uint32_t csrc = (buffer_[12 + index] << 24) | (buffer_[13 + index] << 16) | - (buffer_[14 + index] << 8) | buffer_[15 + index]; - csrcs_.push_back(csrc); - } - - uint32_t extension_offset = total_csrc_number_ * 4; - if (has_extension_) { - extension_profile_ = - (buffer_[12 + extension_offset] << 8) | buffer_[13 + extension_offset]; - extension_len_ = - (buffer_[14 + extension_offset] << 8) | buffer_[15 + extension_offset]; - - // extension_data_ = new uint8_t[extension_len_]; - // memcpy(extension_data_, buffer_ + 16 + extension_offset, - // extension_len_); - extension_data_ = buffer_ + 16 + extension_offset; - } - - uint32_t payload_offset = - (has_extension_ ? extension_len_ : 0) + extension_offset; - - fu_indicator_.forbidden_bit = (buffer_[12 + payload_offset] >> 7) & 0x01; - fu_indicator_.nal_reference_idc = (buffer_[12 + payload_offset] >> 5) & 0x03; - fu_indicator_.nal_unit_type = buffer_[12 + payload_offset] & 0x1F; - - payload_size_ = size_ - (13 + payload_offset); - payload_ = buffer_ + 13 + payload_offset; - if (payload) { - memcpy(payload, payload_, payload_size_); - } - return payload_size_; -} - -size_t RtpPacket::DecodeH264Fua(uint8_t *payload) { - version_ = (buffer_[0] >> 6) & 0x03; - has_padding_ = (buffer_[0] >> 5) & 0x01; - has_extension_ = (buffer_[0] >> 4) & 0x01; - total_csrc_number_ = buffer_[0] & 0x0f; - marker_ = (buffer_[1] >> 7) & 0x01; - payload_type_ = buffer_[1] & 0x7f; - sequence_number_ = (buffer_[2] << 8) | buffer_[3]; - timestamp_ = - (buffer_[4] << 24) | (buffer_[5] << 16) | (buffer_[6] << 8) | buffer_[7]; - ssrc_ = (buffer_[8] << 24) | (buffer_[9] << 16) | (buffer_[10] << 8) | - buffer_[11]; - - for (uint32_t index = 0; index < total_csrc_number_; index++) { - uint32_t csrc = (buffer_[12 + index] << 24) | (buffer_[13 + index] << 16) | - (buffer_[14 + index] << 8) | buffer_[15 + index]; - csrcs_.push_back(csrc); - } - - uint32_t extension_offset = total_csrc_number_ * 4; - if (has_extension_) { - extension_profile_ = - (buffer_[12 + extension_offset] << 8) | buffer_[13 + extension_offset]; - extension_len_ = - (buffer_[14 + extension_offset] << 8) | buffer_[15 + extension_offset]; - - extension_data_ = buffer_ + 16 + extension_offset; - } - - uint32_t payload_offset = - (has_extension_ ? extension_len_ : 0) + extension_offset; - - fu_indicator_.forbidden_bit = (buffer_[12 + payload_offset] >> 7) & 0x01; - fu_indicator_.nal_reference_idc = (buffer_[12 + payload_offset] >> 5) & 0x03; - fu_indicator_.nal_unit_type = buffer_[12 + payload_offset] & 0x1F; - - fu_header_.start = (buffer_[13 + payload_offset] >> 7) & 0x01; - fu_header_.end = (buffer_[13 + payload_offset] >> 6) & 0x01; - fu_header_.remain_bit = (buffer_[13 + payload_offset] >> 5) & 0x01; - fu_header_.nal_unit_type = buffer_[13 + payload_offset] & 0x1F; - - payload_size_ = size_ - (14 + payload_offset); - payload_ = buffer_ + 14 + payload_offset; - if (payload) { - memcpy(payload, payload_, payload_size_); - } - return payload_size_; -} - -size_t RtpPacket::DecodeH264FecSource(uint8_t *payload) { - version_ = (buffer_[0] >> 6) & 0x03; - has_padding_ = (buffer_[0] >> 5) & 0x01; - has_extension_ = (buffer_[0] >> 4) & 0x01; - total_csrc_number_ = buffer_[0] & 0x0f; - marker_ = (buffer_[1] >> 7) & 0x01; - payload_type_ = buffer_[1] & 0x7f; - sequence_number_ = (buffer_[2] << 8) | buffer_[3]; - timestamp_ = - (buffer_[4] << 24) | (buffer_[5] << 16) | (buffer_[6] << 8) | buffer_[7]; - ssrc_ = (buffer_[8] << 24) | (buffer_[9] << 16) | (buffer_[10] << 8) | - buffer_[11]; - - for (uint32_t index = 0; index < total_csrc_number_; index++) { - uint32_t csrc = (buffer_[12 + index] << 24) | (buffer_[13 + index] << 16) | - (buffer_[14 + index] << 8) | buffer_[15 + index]; - csrcs_.push_back(csrc); - } - - uint32_t extension_offset = total_csrc_number_ * 4; - if (has_extension_) { - extension_profile_ = - (buffer_[12 + extension_offset] << 8) | buffer_[13 + extension_offset]; - extension_len_ = - (buffer_[14 + extension_offset] << 8) | buffer_[15 + extension_offset]; - - extension_data_ = buffer_ + 16 + extension_offset; - } - - uint32_t fec_symbol_id_offset = - extension_offset + (has_extension_ ? extension_len_ : 0); - fec_symbol_id_ = buffer_[12 + fec_symbol_id_offset]; - - uint32_t fec_source_symbol_num_offset = fec_symbol_id_offset + 1; - fec_source_symbol_num_ = buffer_[12 + fec_source_symbol_num_offset]; - - uint32_t payload_offset = fec_source_symbol_num_offset + 1; - - fu_indicator_.forbidden_bit = (buffer_[12 + payload_offset] >> 7) & 0x01; - fu_indicator_.nal_reference_idc = (buffer_[12 + payload_offset] >> 5) & 0x03; - fu_indicator_.nal_unit_type = buffer_[12 + payload_offset] & 0x1F; - - fu_header_.start = (buffer_[13 + payload_offset] >> 7) & 0x01; - fu_header_.end = (buffer_[13 + payload_offset] >> 6) & 0x01; - fu_header_.remain_bit = (buffer_[13 + payload_offset] >> 5) & 0x01; - fu_header_.nal_unit_type = buffer_[13 + payload_offset] & 0x1F; - - payload_size_ = size_ - (14 + payload_offset); - payload_ = buffer_ + 14 + payload_offset; - if (payload) { - memcpy(payload, payload_, payload_size_); - } - return payload_size_; -} - -size_t RtpPacket::DecodeH264FecRepair(uint8_t *payload) { - version_ = (buffer_[0] >> 6) & 0x03; - has_padding_ = (buffer_[0] >> 5) & 0x01; - has_extension_ = (buffer_[0] >> 4) & 0x01; - total_csrc_number_ = buffer_[0] & 0x0f; - marker_ = (buffer_[1] >> 7) & 0x01; - payload_type_ = buffer_[1] & 0x7f; - sequence_number_ = (buffer_[2] << 8) | buffer_[3]; - timestamp_ = - (buffer_[4] << 24) | (buffer_[5] << 16) | (buffer_[6] << 8) | buffer_[7]; - ssrc_ = (buffer_[8] << 24) | (buffer_[9] << 16) | (buffer_[10] << 8) | - buffer_[11]; - - for (uint32_t index = 0; index < total_csrc_number_; index++) { - uint32_t csrc = (buffer_[12 + index] << 24) | (buffer_[13 + index] << 16) | - (buffer_[14 + index] << 8) | buffer_[15 + index]; - csrcs_.push_back(csrc); - } - - uint32_t extension_offset = total_csrc_number_ * 4; - if (has_extension_) { - extension_profile_ = - (buffer_[12 + extension_offset] << 8) | buffer_[13 + extension_offset]; - extension_len_ = - (buffer_[14 + extension_offset] << 8) | buffer_[15 + extension_offset]; - - extension_data_ = buffer_ + 16 + extension_offset; - } - - uint32_t fec_symbol_id_offset = - extension_offset + (has_extension_ ? extension_len_ : 0); - fec_symbol_id_ = buffer_[12 + fec_symbol_id_offset]; - - uint32_t fec_source_symbol_num_offset = fec_symbol_id_offset + 1; - fec_source_symbol_num_ = buffer_[12 + fec_source_symbol_num_offset]; - - uint32_t payload_offset = fec_source_symbol_num_offset + 1; - - payload_size_ = size_ - (14 + payload_offset); - payload_ = buffer_ + 14 + payload_offset; - if (payload) { - memcpy(payload, payload_, payload_size_); - } - return payload_size_; -} - -size_t RtpPacket::DecodeAv1(uint8_t *payload) { - version_ = (buffer_[0] >> 6) & 0x03; - has_padding_ = (buffer_[0] >> 5) & 0x01; - has_extension_ = (buffer_[0] >> 4) & 0x01; - total_csrc_number_ = buffer_[0] & 0x0f; - marker_ = (buffer_[1] >> 7) & 0x01; - payload_type_ = buffer_[1] & 0x7f; - sequence_number_ = (buffer_[2] << 8) | buffer_[3]; - timestamp_ = - (buffer_[4] << 24) | (buffer_[5] << 16) | (buffer_[6] << 8) | buffer_[7]; - ssrc_ = (buffer_[8] << 24) | (buffer_[9] << 16) | (buffer_[10] << 8) | - buffer_[11]; - - for (uint32_t index = 0; index < total_csrc_number_; index++) { - uint32_t csrc = (buffer_[12 + index] << 24) | (buffer_[13 + index] << 16) | - (buffer_[14 + index] << 8) | buffer_[15 + index]; - csrcs_.push_back(csrc); - } - - uint32_t extension_offset = total_csrc_number_ * 4; - if (has_extension_) { - extension_profile_ = - (buffer_[12 + extension_offset] << 8) | buffer_[13 + extension_offset]; - extension_len_ = - (buffer_[14 + extension_offset] << 8) | buffer_[15 + extension_offset]; - - // extension_data_ = new uint8_t[extension_len_]; - // memcpy(extension_data_, buffer_ + 16 + extension_offset, - // extension_len_); - extension_data_ = buffer_ + 16 + extension_offset; - } - - uint32_t aggr_header_offset = - (has_extension_ ? extension_len_ : 0) + extension_offset; - - av1_aggr_header_ = buffer_[12 + aggr_header_offset]; - - uint32_t payload_offset = aggr_header_offset; - - payload_size_ = size_ - (13 + payload_offset); - payload_ = buffer_ + 13 + payload_offset; - if (payload) { - memcpy(payload, payload_, payload_size_); - } - - return payload_size_; + return true; } \ No newline at end of file diff --git a/src/rtp/rtp_packet/rtp_packet.h b/src/rtp/rtp_packet/rtp_packet.h index f73a946..40e2bd1 100644 --- a/src/rtp/rtp_packet/rtp_packet.h +++ b/src/rtp/rtp_packet/rtp_packet.h @@ -6,7 +6,9 @@ #include #include +#include "copy_on_write_buffer.h" #include "log.h" +#include "rtp_header.h" // Common // 0 1 2 3 @@ -180,12 +182,13 @@ class RtpPacket { DATA = 127 } PAYLOAD_TYPE; - typedef enum { UNKNOWN = 0, NALU = 1, FU_A = 28, FU_B = 29 } NAL_UNIT_TYPE; + constexpr uint16_t kOneByteExtensionProfileId = 0xBEDE; + constexpr uint16_t kTwoByteExtensionProfileId = 0x1000; + + constexpr size_t kFixedHeaderSize = 12; public: RtpPacket(); - RtpPacket(uint32_t size); - RtpPacket(const uint8_t *buffer, uint32_t size); RtpPacket(const RtpPacket &rtp_packet); RtpPacket(RtpPacket &&rtp_packet); RtpPacket &operator=(const RtpPacket &rtp_packet); @@ -212,15 +215,6 @@ class RtpPacket { void SetSsrc(uint32_t ssrc) { ssrc_ = ssrc; } void SetCsrcs(std::vector &csrcs) { csrcs_ = csrcs; } - void SetExtensionProfile(uint16_t extension_profile) { - // extension_profile_ = extension_profile; - } - void SetExtensionData(uint8_t *extension_data, uint16_t extension_len) { - // extension_len_ = extension_len; - // extension_data_ = new uint8_t[extension_len_]; - // memcpy(extension_data_, extension_data, extension_len_); - } - void SetAbsoluteSendTimestamp(uint32_t abs_send_time) { // Absolute Send Time is a 24-bit field, we need to ensure it fits in 24 // bits @@ -235,7 +229,7 @@ class RtpPacket { } // Set the extension profile to 0xBEDE (one-byte header) - extension_profile_ = 0xBEDE; + extension_profile_ = kOneByteExtensionProfileId; // Set the length of the extension data (in 32-bit words minus one) extension_data_[0] = 0x00; @@ -247,238 +241,74 @@ class RtpPacket { extension_data_[4] = abs_send_time & 0xFF; } - public: - typedef struct { - uint8_t forbidden_bit : 1; - uint8_t nal_reference_idc : 2; - uint8_t nal_unit_type : 5; - } FU_INDICATOR; - - typedef struct { - uint8_t start : 1; - uint8_t end : 1; - uint8_t remain_bit : 1; - uint8_t nal_unit_type : 5; - } FU_HEADER; - - void SetFuIndicator(FU_INDICATOR fu_indicator) { - fu_indicator_.forbidden_bit = fu_indicator.forbidden_bit; - fu_indicator_.nal_reference_idc = fu_indicator.nal_reference_idc; - fu_indicator_.nal_unit_type = fu_indicator.nal_unit_type; - } - - void SetFuHeader(FU_HEADER fu_header) { - fu_header_.start = fu_header.start; - fu_header_.end = fu_header.end; - fu_header_.remain_bit = fu_header.remain_bit; - fu_header_.nal_unit_type = fu_header.nal_unit_type; - } - - void SetAv1AggrHeader(int z, int y, int w, int n) { - if (z) av1_aggr_header_ |= (1 << 7); - if (y) av1_aggr_header_ |= (1 << 6); - if (w) av1_aggr_header_ |= w << 4; - if (n) av1_aggr_header_ |= (1 << 3); - } - - void SetFecSymbolId(uint8_t fec_symbol_id) { fec_symbol_id_ = fec_symbol_id; } - - public: - const uint8_t *Encode(uint8_t *payload, size_t payload_size); - const uint8_t *EncodeH264Nalu(uint8_t *payload, size_t payload_size); - const uint8_t *EncodeH264Fua(uint8_t *payload, size_t payload_size); - const uint8_t *EncodeH264FecSource(uint8_t *payload, size_t payload_size, - uint8_t fec_symbol_id, - uint8_t fec_source_symbol_num); - const uint8_t *EncodeH264FecRepair(uint8_t *payload, size_t payload_size, - uint8_t fec_symbol_id, - uint8_t fec_source_symbol_num); - const uint8_t *EncodeAv1(uint8_t *payload, size_t payload_size); - - size_t DecodeData(uint8_t *payload = nullptr); - size_t DecodeH264Nalu(uint8_t *payload = nullptr); - size_t DecodeH264Fua(uint8_t *payload = nullptr); - size_t DecodeH264FecSource(uint8_t *payload = nullptr); - size_t DecodeH264FecRepair(uint8_t *payload = nullptr); - size_t DecodeAv1(uint8_t *payload = nullptr); - size_t DecodeOpus(uint8_t *payload = nullptr); - public: // Get Header - uint32_t Verion() const { - // // ParseRtpData(); - return version_; - } - bool HasPadding() const { - // ParseRtpData(); - return has_padding_; - } - bool HasExtension() const { - // ParseRtpData(); - return has_extension_; - } - bool Marker() const { - // // ParseRtpData(); - return marker_; - } - PAYLOAD_TYPE PayloadType() const { - // ParseRtpData(); - return PAYLOAD_TYPE(payload_type_); - } - uint16_t SequenceNumber() const { - // ParseRtpData(); - return sequence_number_; - } - uint64_t Timestamp() const { - // ParseRtpData(); - return timestamp_; - } - uint32_t Ssrc() const { - // ParseRtpData(); - return ssrc_; - } - std::vector Csrcs() const { - // ParseRtpData(); - return csrcs_; - }; - uint16_t ExtensionProfile() const { - // ParseRtpData(); - return extension_profile_; - } - const uint8_t *ExtensionData() { - // ParseRtpData(); - return extension_data_; - } - - uint32_t GetAbsoluteSendTimestamp(uint32_t *abs_send_time) const { - if (extension_data_ == nullptr || extension_len_ < 4) { - return 0; - } - - // Absolute Send Time is a 24-bit field - *abs_send_time = (extension_data_[2] << 16) | (extension_data_[3] << 8) | - extension_data_[4]; - - return *abs_send_time; - } - - uint8_t FecSymbolId() { return fec_symbol_id_; } - - uint8_t FecSourceSymbolNum() { return fec_source_symbol_num_; } - - void GetAv1AggrHeader(int &z, int &y, int &w, int &n) { - z = av1_aggr_header_ >> 7; - y = av1_aggr_header_ >> 6 & 0x01; - w = av1_aggr_header_ >> 4 & 0x03; - n = av1_aggr_header_ >> 3 & 0x01; - } + uint32_t Verion() const { return version_; } + bool HasPadding() const { return has_padding_; } + bool HasExtension() const { return has_extension_; } + bool Marker() const { return marker_; } + PAYLOAD_TYPE PayloadType() const { return PAYLOAD_TYPE(payload_type_); } + uint16_t SequenceNumber() const { return sequence_number_; } + uint64_t Timestamp() const { return timestamp_; } + uint32_t Ssrc() const { return ssrc_; } + std::vector Csrcs() const { return csrcs_; }; + uint16_t ExtensionProfile() const { return extension_profile_; } + const uint8_t *ExtensionData() { return extension_data_; } // Payload - const uint8_t *Payload() { - // ParseRtpData(); - return payload_; - }; - size_t PayloadSize() { - // ParseRtpData(); - return payload_size_; - } - - size_t headers_size() const { return 12; } - - size_t payload_size() const { return payload_size_; } - - bool has_padding() const { return buffer_[0] & 0x20; } - - size_t padding_size() const { return padding_size_; } + const uint8_t *Payload() { return Buffer() + payload_offset_; }; + size_t PayloadSize() { return payload_size_; } // Entire RTP buffer const uint8_t *Buffer() const { return buffer_; } size_t Size() const { return size_; } + + // For webrtc module use + size_t headers_size() const { return payload_offset_; } + size_t payload_size() const { return payload_size_; } + bool has_padding() const { return buffer_[0] & 0x20; } + size_t padding_size() const { return padding_size_; } size_t size() const { return size_; } - // NAL - NAL_UNIT_TYPE NalUnitType() { - // ParseRtpData(); - return nal_unit_type_; - } - bool FuAStart() { - // ParseRtpData(); - return fu_header_.start; - } - bool FuAEnd() { - // ParseRtpData(); - return fu_header_.end; - } - - bool Av1FrameStart() { - // ParseRtpData(); - int z, y, w, n; - GetAv1AggrHeader(z, y, w, n); - // return !z && !y; - - if (z == 0 && y == 0 && w == 1) { - return true; - } else if (z == 0 && y == 1 && w == 1) { - return true; - } else { - return false; - } - } - - bool Av1FrameEnd() { - // ParseRtpData(); - int z, y, w, n; - GetAv1AggrHeader(z, y, w, n); - // return z && !y; - - if (z == 0 && y == 0 && w == 1) { - return true; - } else if (z == 1 && y == 0 && w == 1) { - return true; - } else { - return false; - } - } - private: - void TryToDecodeRtpPacket(); - void ParseRtpData(); - - private: - // Header + // Common header uint8_t version_ = 0; bool has_padding_ = false; bool has_extension_ = false; - uint8_t total_csrc_number_ = 0; + uint8_t csrc_count_ = 0; bool marker_ = false; uint8_t payload_type_ = 0; uint16_t sequence_number_ = 1; uint64_t timestamp_ = 0; uint32_t ssrc_ = 0; std::vector csrcs_; - uint16_t profile_ = 0; + + // Extension header uint16_t extension_profile_ = 0; uint16_t extension_len_ = 0; - uint8_t *extension_data_ = nullptr; + struct Extension { + uint8_t id; + std::vector data; + }; + std::vector extensions_; + + // Payload + size_t payload_offset_ = 0; + size_t payload_size_ = 0; + + // Padding + size_t padding_size_ = 0; + + // Entire rtp buffer + CopyOnWriteBuffer buffer_ = nullptr; + size_t size_ = 0; + + // H.264 header FU_INDICATOR fu_indicator_; FU_HEADER fu_header_; uint8_t fec_symbol_id_ = 0; uint8_t fec_source_symbol_num_ = 0; uint8_t av1_aggr_header_ = 0; - - // Payload - uint8_t *payload_ = nullptr; - size_t payload_size_ = 0; - size_t padding_size_ = 0; - - // Entire RTP buffer - uint8_t *buffer_ = nullptr; - size_t size_ = 0; - - // NAL - NAL_UNIT_TYPE nal_unit_type_ = NAL_UNIT_TYPE::UNKNOWN; - - bool parsed_ = false; }; #endif \ No newline at end of file diff --git a/src/rtp/rtp_packet/rtp_packet.hxx b/src/rtp/rtp_packet/rtp_packet.hxx new file mode 100644 index 0000000..75e08e4 --- /dev/null +++ b/src/rtp/rtp_packet/rtp_packet.hxx @@ -0,0 +1,484 @@ +#ifndef _RTP_PACKET_H_ +#define _RTP_PACKET_H_ + +#include +#include +#include +#include + +#include "log.h" + +// Common +// 0 1 2 3 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// |V=2|P|X| CC |M| PT | sequence number | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | timestamp | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | synchronization source (SSRC) identifier | +// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +// | Contributing source (CSRC) identifiers |x +// | .... |x +// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +// | defined by profile | length |x +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | Extensions |x +// | .... |x +// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +// | Payload | +// | .... : padding... | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | padding | Padding size | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +// H264 +// 0 1 2 3 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// |V=2|P|X| CC |M| PT | sequence number | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | timestamp | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | synchronization source (SSRC) identifier | +// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +// | Contributing source (CSRC) identifiers |x +// | .... |x +// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +// | defined by profile | length |x +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | Extensions |x +// | .... |x +// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +// | FU indicator | FU header | | +// | | +// | FU Payload | +// | | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | padding | Padding size | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +// | FU indicator | FU header | +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// |F|NRI| Type |S|E|R| Type | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +// H264 FEC source symbol +// 0 1 2 3 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// |V=2|P|X| CC |M| PT | sequence number | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | timestamp | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | synchronization source (SSRC) identifier | +// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +// | Contributing source (CSRC) identifiers |x +// | .... |x +// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +// | defined by profile | length |x +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | Extensions |x +// | .... |x +// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +// | FEC symbol id | src sym num | FU indicator | FU header | +// | | +// | FU Payload | +// | | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | padding | Padding size | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +// H264 FEC repair symbol +// 0 1 2 3 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// |V=2|P|X| CC |M| PT | sequence number | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | timestamp | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | synchronization source (SSRC) identifier | +// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +// | Contributing source (CSRC) identifiers |x +// | .... |x +// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +// | defined by profile | length |x +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | Extensions |x +// | .... |x +// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +// | FEC symbol id | src sym num | | +// | | +// | Fec Payload | +// | | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | padding | Padding size | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +// AV1 +// 0 1 2 3 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// |V=2|P|X| CC |M| PT | sequence number | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | timestamp | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | synchronization source (SSRC) identifier | +// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +// | contributing source (CSRC) identifiers |x +// | .... |x +// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +// | 0x100 | 0x0 | extensions length |x +// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +// | ID | hdr_length | |x +// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ |x +// | |x +// | dependency descriptor (hdr_length #bytes) |x +// | |x +// | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | | Other rtp header extensions...|x +// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +// | AV1 aggr hdr | | +// +-+-+-+-+-+-+-+-+ | +// | | +// | Bytes 2..N of AV1 payload | +// | | +// | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | : OPTIONAL RTP padding | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +// | AV1 aggr hdr | +// +// Z=1: first obu element is an obu fragment that is a continuation of an OBU +// fragment from the previous packet. +// +// Y=1: the last OBU element is an OBU fragment that will continue in the next +// packet. +// +// W=1: two bit field that describes the number of OBU elements in the packet. +// +// N=1: the packet is the first packet of a coded video sequence. +// +// 0 1 2 3 4 5 6 7 +// +-+-+-+-+-+-+-+-+ +// |Z|Y| W |N|-|-|-| +// +-+-+-+-+-+-+-+-+ + +#define DEFAULT_MTU 1500 +#define MAX_NALU_LEN 1400 + +class RtpPacket { + public: + typedef enum { + UNDEFINED = 0, + H264 = 96, + H264_FEC_SOURCE = 97, + H264_FEC_REPAIR = 98, + AV1 = 99, + OPUS = 111, + DATA = 127 + } PAYLOAD_TYPE; + + typedef enum { UNKNOWN = 0, NALU = 1, FU_A = 28, FU_B = 29 } NAL_UNIT_TYPE; + + public: + RtpPacket(); + RtpPacket(uint32_t size); + RtpPacket(const uint8_t *buffer, uint32_t size); + RtpPacket(const RtpPacket &rtp_packet); + RtpPacket(RtpPacket &&rtp_packet); + RtpPacket &operator=(const RtpPacket &rtp_packet); + RtpPacket &operator=(RtpPacket &&rtp_packet); + + virtual ~RtpPacket(); + + public: + bool Build(const uint8_t *buffer, uint32_t size); + + public: + // Set Header + void SetVerion(uint8_t version) { version_ = version; } + void SetHasPadding(bool has_padding) { has_padding_ = has_padding; } + void SetHasExtension(bool has_extension) { has_extension_ = has_extension; } + void SetMarker(bool marker) { marker_ = marker; } + void SetPayloadType(PAYLOAD_TYPE payload_type) { + payload_type_ = (uint8_t)payload_type; + } + void SetSequenceNumber(uint16_t sequence_number) { + sequence_number_ = sequence_number; + } + void SetTimestamp(uint64_t timestamp) { timestamp_ = timestamp; } + void SetSsrc(uint32_t ssrc) { ssrc_ = ssrc; } + void SetCsrcs(std::vector &csrcs) { csrcs_ = csrcs; } + + void SetExtensionProfile(uint16_t extension_profile) { + // extension_profile_ = extension_profile; + } + void SetExtensionData(uint8_t *extension_data, uint16_t extension_len) { + // extension_len_ = extension_len; + // extension_data_ = new uint8_t[extension_len_]; + // memcpy(extension_data_, extension_data, extension_len_); + } + + void SetAbsoluteSendTimestamp(uint32_t abs_send_time) { + // Absolute Send Time is a 24-bit field, we need to ensure it fits in 24 + // bits + abs_send_time &= 0x00FFFFFF; + + // Allocate memory for the extension data if not already allocated + if (extension_data_ == nullptr) { + extension_data_ = + (uint8_t *)malloc(5); // 2 bytes for profile, 2 bytes for length, 3 + // bytes for abs_send_time + extension_len_ = 5; + } + + // Set the extension profile to 0xBEDE (one-byte header) + extension_profile_ = 0xBEDE; + + // Set the length of the extension data (in 32-bit words minus one) + extension_data_[0] = 0x00; + extension_data_[1] = 0x02; // 2 words (8 bytes) + + // Set the absolute send time in the extension data + extension_data_[2] = (abs_send_time >> 16) & 0xFF; + extension_data_[3] = (abs_send_time >> 8) & 0xFF; + extension_data_[4] = abs_send_time & 0xFF; + } + + public: + typedef struct { + uint8_t forbidden_bit : 1; + uint8_t nal_reference_idc : 2; + uint8_t nal_unit_type : 5; + } FU_INDICATOR; + + typedef struct { + uint8_t start : 1; + uint8_t end : 1; + uint8_t remain_bit : 1; + uint8_t nal_unit_type : 5; + } FU_HEADER; + + void SetFuIndicator(FU_INDICATOR fu_indicator) { + fu_indicator_.forbidden_bit = fu_indicator.forbidden_bit; + fu_indicator_.nal_reference_idc = fu_indicator.nal_reference_idc; + fu_indicator_.nal_unit_type = fu_indicator.nal_unit_type; + } + + void SetFuHeader(FU_HEADER fu_header) { + fu_header_.start = fu_header.start; + fu_header_.end = fu_header.end; + fu_header_.remain_bit = fu_header.remain_bit; + fu_header_.nal_unit_type = fu_header.nal_unit_type; + } + + void SetAv1AggrHeader(int z, int y, int w, int n) { + if (z) av1_aggr_header_ |= (1 << 7); + if (y) av1_aggr_header_ |= (1 << 6); + if (w) av1_aggr_header_ |= w << 4; + if (n) av1_aggr_header_ |= (1 << 3); + } + + void SetFecSymbolId(uint8_t fec_symbol_id) { fec_symbol_id_ = fec_symbol_id; } + + public: + const uint8_t *Encode(uint8_t *payload, size_t payload_size); + const uint8_t *EncodeH264Nalu(uint8_t *payload, size_t payload_size); + const uint8_t *EncodeH264Fua(uint8_t *payload, size_t payload_size); + const uint8_t *EncodeH264FecSource(uint8_t *payload, size_t payload_size, + uint8_t fec_symbol_id, + uint8_t fec_source_symbol_num); + const uint8_t *EncodeH264FecRepair(uint8_t *payload, size_t payload_size, + uint8_t fec_symbol_id, + uint8_t fec_source_symbol_num); + const uint8_t *EncodeAv1(uint8_t *payload, size_t payload_size); + + size_t DecodeData(uint8_t *payload = nullptr); + size_t DecodeH264Nalu(uint8_t *payload = nullptr); + size_t DecodeH264Fua(uint8_t *payload = nullptr); + size_t DecodeH264FecSource(uint8_t *payload = nullptr); + size_t DecodeH264FecRepair(uint8_t *payload = nullptr); + size_t DecodeAv1(uint8_t *payload = nullptr); + size_t DecodeOpus(uint8_t *payload = nullptr); + + public: + // Get Header + uint32_t Verion() const { + // // ParseRtpData(); + return version_; + } + bool HasPadding() const { + // ParseRtpData(); + return has_padding_; + } + bool HasExtension() const { + // ParseRtpData(); + return has_extension_; + } + bool Marker() const { + // // ParseRtpData(); + return marker_; + } + PAYLOAD_TYPE PayloadType() const { + // ParseRtpData(); + return PAYLOAD_TYPE(payload_type_); + } + uint16_t SequenceNumber() const { + // ParseRtpData(); + return sequence_number_; + } + uint64_t Timestamp() const { + // ParseRtpData(); + return timestamp_; + } + uint32_t Ssrc() const { + // ParseRtpData(); + return ssrc_; + } + std::vector Csrcs() const { + // ParseRtpData(); + return csrcs_; + }; + uint16_t ExtensionProfile() const { + // ParseRtpData(); + return extension_profile_; + } + const uint8_t *ExtensionData() { + // ParseRtpData(); + return extension_data_; + } + + uint32_t GetAbsoluteSendTimestamp(uint32_t *abs_send_time) const { + if (extension_data_ == nullptr || extension_len_ < 4) { + return 0; + } + + // Absolute Send Time is a 24-bit field + *abs_send_time = (extension_data_[2] << 16) | (extension_data_[3] << 8) | + extension_data_[4]; + + return *abs_send_time; + } + + uint8_t FecSymbolId() { return fec_symbol_id_; } + + uint8_t FecSourceSymbolNum() { return fec_source_symbol_num_; } + + void GetAv1AggrHeader(int &z, int &y, int &w, int &n) { + z = av1_aggr_header_ >> 7; + y = av1_aggr_header_ >> 6 & 0x01; + w = av1_aggr_header_ >> 4 & 0x03; + n = av1_aggr_header_ >> 3 & 0x01; + } + + // Payload + const uint8_t *Payload() { + // ParseRtpData(); + return payload_; + }; + size_t PayloadSize() { + // ParseRtpData(); + return payload_size_; + } + + size_t headers_size() const { return 12; } + + size_t payload_size() const { return payload_size_; } + + bool has_padding() const { return buffer_[0] & 0x20; } + + size_t padding_size() const { return padding_size_; } + + // Entire RTP buffer + const uint8_t *Buffer() const { return buffer_; } + size_t Size() const { return size_; } + size_t size() const { return size_; } + + // NAL + NAL_UNIT_TYPE NalUnitType() { + // ParseRtpData(); + return nal_unit_type_; + } + bool FuAStart() { + // ParseRtpData(); + return fu_header_.start; + } + bool FuAEnd() { + // ParseRtpData(); + return fu_header_.end; + } + + bool Av1FrameStart() { + // ParseRtpData(); + int z, y, w, n; + GetAv1AggrHeader(z, y, w, n); + // return !z && !y; + + if (z == 0 && y == 0 && w == 1) { + return true; + } else if (z == 0 && y == 1 && w == 1) { + return true; + } else { + return false; + } + } + + bool Av1FrameEnd() { + // ParseRtpData(); + int z, y, w, n; + GetAv1AggrHeader(z, y, w, n); + // return z && !y; + + if (z == 0 && y == 0 && w == 1) { + return true; + } else if (z == 1 && y == 0 && w == 1) { + return true; + } else { + return false; + } + } + + private: + void TryToDecodeRtpPacket(); + void ParseRtpData(); + + private: + // Header + uint8_t version_ = 0; + bool has_padding_ = false; + bool has_extension_ = false; + uint8_t csrc_count_ = 0; + bool marker_ = false; + uint8_t payload_type_ = 0; + uint16_t sequence_number_ = 1; + uint64_t timestamp_ = 0; + uint32_t ssrc_ = 0; + std::vector csrcs_; + uint16_t profile_ = 0; + uint16_t extension_profile_ = 0; + uint16_t extension_len_ = 0; + uint8_t *extension_data_ = nullptr; + FU_INDICATOR fu_indicator_; + FU_HEADER fu_header_; + uint8_t fec_symbol_id_ = 0; + uint8_t fec_source_symbol_num_ = 0; + uint8_t av1_aggr_header_ = 0; + + // Payload + uint8_t *payload_ = nullptr; + size_t payload_size_ = 0; + size_t padding_size_ = 0; + + // Entire RTP buffer + uint8_t *buffer_ = nullptr; + size_t size_ = 0; + + // NAL + NAL_UNIT_TYPE nal_unit_type_ = NAL_UNIT_TYPE::UNKNOWN; + + bool parsed_ = false; +}; + +#endif \ No newline at end of file diff --git a/src/rtp/rtp_packet/rtp_packet_received.cpp b/src/rtp/rtp_packet/rtp_packet_received.cpp index eb1dddf..eaa89c9 100644 --- a/src/rtp/rtp_packet/rtp_packet_received.cpp +++ b/src/rtp/rtp_packet/rtp_packet_received.cpp @@ -33,18 +33,21 @@ RtpPacketReceived& RtpPacketReceived::operator=(RtpPacketReceived&& packet) = RtpPacketReceived::~RtpPacketReceived() {} void RtpPacketReceived::GetHeader(RTPHeader* header) const { - header->markerBit = Marker(); - header->payloadType = PayloadType(); - header->sequenceNumber = SequenceNumber(); - header->timestamp = Timestamp(); - header->ssrc = Ssrc(); + header->version = Version(); + header->has_padding_ = HasPadding(); + header->has_extension_ = HasExtension(); + header->csrc_count_ = Csrcs().size(); + header->marker_ = Marker(); + header->payload_type_ = PayloadType(); + header->sequence_number_ = SequenceNumber(); + header->timestamp_ = Timestamp(); + header->ssrc_ = Ssrc(); std::vector csrcs = Csrcs(); - header->numCSRCs = rtc::dchecked_cast(csrcs.size()); for (size_t i = 0; i < csrcs.size(); ++i) { - header->arrOfCSRCs[i] = csrcs[i]; + header->csrc_[i] = csrcs[i]; } - header->paddingLength = padding_size(); - header->headerLength = headers_size(); + header->padding_len = padding_size(); + header->header_len = headers_size(); } } // namespace webrtc diff --git a/src/rtp/rtp_packetizer/rtp_packetizer.cpp b/src/rtp/rtp_packetizer/rtp_packetizer.cpp new file mode 100644 index 0000000..dbeea34 --- /dev/null +++ b/src/rtp/rtp_packetizer/rtp_packetizer.cpp @@ -0,0 +1,11 @@ +#include "rtp_packetizer.h" + +std::unique_ptr Create(uint32_t payload_type, uint8_t* payload, + size_t payload_size) { + switch (payload_type) { + case RtpPacket::PAYLOAD_TYPE::H264: + return std::make_unique(payload, payload_size); + case RtpPacket::PAYLOAD_TYPE::AV1: + return std::make_unique(payload, payload_size); + } +} \ No newline at end of file diff --git a/src/rtp/rtp_packetizer/rtp_packetizer.h b/src/rtp/rtp_packetizer/rtp_packetizer.h new file mode 100644 index 0000000..95ef409 --- /dev/null +++ b/src/rtp/rtp_packetizer/rtp_packetizer.h @@ -0,0 +1,25 @@ +/* + * @Author: DI JUNKUN + * @Date: 2025-01-22 + * Copyright (c) 2025 by DI JUNKUN, All Rights Reserved. + */ + +#ifndef _RTP_PACKETIZER_H_ +#define _RTP_PACKETIZER_H_ + +#include +#include +#include + +#include "rtp_packet.h" + +class RtpPacketizer { + public: + static std::unique_ptr Create(uint32_t payload_type); + + virtual ~RtpPacketizer() = default; + + bool Build(uint8_t* payload, uint32_t payload_size) = 0; +}; + +#endif \ No newline at end of file diff --git a/src/rtp/rtp_packetizer/rtp_packetizer_av1.cpp b/src/rtp/rtp_packetizer/rtp_packetizer_av1.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/rtp/rtp_packetizer/rtp_packetizer_av1.h b/src/rtp/rtp_packetizer/rtp_packetizer_av1.h new file mode 100644 index 0000000..e69de29 diff --git a/src/rtp/rtp_packetizer/rtp_packetizer_generic.cpp b/src/rtp/rtp_packetizer/rtp_packetizer_generic.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/rtp/rtp_packetizer/rtp_packetizer_generic.h b/src/rtp/rtp_packetizer/rtp_packetizer_generic.h new file mode 100644 index 0000000..e69de29 diff --git a/src/rtp/rtp_packetizer/rtp_packetizer_h264.cpp b/src/rtp/rtp_packetizer/rtp_packetizer_h264.cpp new file mode 100644 index 0000000..2881b7b --- /dev/null +++ b/src/rtp/rtp_packetizer/rtp_packetizer_h264.cpp @@ -0,0 +1,266 @@ +#include "rtp_packetizer_h264.h" + +RtpPacketizerH264::RtpPacketizerH264() + : version_(kRtpVersion), + has_padding_(false), + has_extension_(true), + csrc_count_(0), + marker_(false), + payload_type_(RtpPacket::PAYLOAD_TYPE::H264), + sequence_number_(1), + timestamp_(0), + ssrc_(0), + profile_(0), + extension_profile_(0), + extension_len_(0), + extension_data_(nullptr) {} + +RtpPacketizerH264::~RtpPacketizerH264() {} + +std::vector RtpPacketizerH264::Build(uint8_t* payload, + uint32_t payload_size) { + uint32_t last_packet_size = payload_size % MAX_NALU_LEN; + uint32_t packet_num = + payload_size / MAX_NALU_LEN + (last_packet_size ? 1 : 0); + + // TODO: use frame timestamp + timestamp_ = std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()) + .count(); + + for (uint32_t index = 0; index < packet_num; index++) { + version_ = kRtpVersion; + has_padding_ = false; + has_extension_ = true; + csrc_count_ = 0; + marker_ = index == packet_num - 1 ? 1 : 0; + payload_type_ = RtpPacket::PAYLOAD_TYPE(payload_type_); + sequence_number_++; + timestamp_ = timestamp_; + ssrc_ = ssrc_; + + if (!csrc_count_) { + csrcs_ = csrcs_; + } + + RtpPacket::FU_INDICATOR fu_indicator; + fu_indicator.forbidden_bit = 0; + fu_indicator.nal_reference_idc = 0; + fu_indicator.nal_unit_type = FU_A; + + RtpPacket::FU_HEADER fu_header; + fu_header.start = index == 0 ? 1 : 0; + fu_header.end = index == packet_num - 1 ? 1 : 0; + fu_header.remain_bit = 0; + fu_header.nal_unit_type = FU_A; + + rtp_packet_frame_.clear(); + rtp_packet_frame_.push_back((version_ << 6) | (has_padding_ << 5) | + (has_extension_ << 4) | csrc_count_); + rtp_packet_frame_.push_back((marker_ << 7) | payload_type_); + rtp_packet_frame_.push_back((sequence_number_ >> 8) & 0xFF); + rtp_packet_frame_.push_back(sequence_number_ & 0xFF); + rtp_packet_frame_.push_back((timestamp_ >> 24) & 0xFF); + rtp_packet_frame_.push_back((timestamp_ >> 16) & 0xFF); + rtp_packet_frame_.push_back((timestamp_ >> 8) & 0xFF); + rtp_packet_frame_.push_back(timestamp_ & 0xFF); + rtp_packet_frame_.push_back((ssrc_ >> 24) & 0xFF); + rtp_packet_frame_.push_back((ssrc_ >> 16) & 0xFF); + rtp_packet_frame_.push_back((ssrc_ >> 8) & 0xFF); + rtp_packet_frame_.push_back(ssrc_ & 0xFF); + + for (uint32_t index = 0; index < csrc_count_ && !csrcs_.empty(); index++) { + rtp_packet_frame_.push_back((csrcs_[index] >> 24) & 0xFF); + rtp_packet_frame_.push_back((csrcs_[index] >> 16) & 0xFF); + rtp_packet_frame_.push_back((csrcs_[index] >> 8) & 0xFF); + rtp_packet_frame_.push_back(csrcs_[index] & 0xFF); + } + + if (has_extension_) { + extension_profile_ = kOneByteExtensionProfileId; + extension_len_ = 5; + + uint32_t abs_send_time = + std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()) + .count(); + + rtp_packet_frame_.push_back(extension_profile_ >> 8); + rtp_packet_frame_.push_back(extension_profile_ & 0xff); + rtp_packet_frame_.push_back((extension_len_ >> 8) & 0xFF); + rtp_packet_frame_.push_back(extension_len_ & 0xFF); + rtp_packet_frame_.push_back(0x00); + rtp_packet_frame_.push_back(0x02); + rtp_packet_frame_.push_back((abs_send_time >> 16) & 0xFF); + rtp_packet_frame_.push_back((abs_send_time >> 8) & 0xFF); + rtp_packet_frame_.push_back(abs_send_time & 0xFF); + } + + rtp_packet_frame_.push_back(fu_indicator.forbidden_bit << 7 | + fu_indicator.nal_reference_idc << 6 | + fu_indicator.nal_unit_type); + + rtp_packet_frame_.push_back(fu_header.start << 7 | fu_header.end << 6 | + fu_header.remain_bit << 1 | + fu_header.nal_unit_type); + + if (index == packet_num - 1 && last_packet_size > 0) { + rtp_packet_frame_.insert(rtp_packet_frame_.end(), payload, + payload + last_packet_size); + } else { + rtp_packet_frame_.insert(rtp_packet_frame_.end(), payload, + payload + MAX_NALU_LEN); + } + + RtpPacket rtp_packet; + rtp_packet.Build(rtp_packet_frame_.data(), rtp_packet_frame_.size()); + + packets.emplace_back(rtp_packet); + } +} + +// bool BuildFec(uint8_t* payload, uint32_t payload_size) { +// uint8_t** fec_packets = +// fec_encoder_.Encode((const char*)payload, payload_size); +// if (nullptr == fec_packets) { +// LOG_ERROR("Invalid fec_packets"); +// return; +// } +// uint8_t num_of_total_packets = 0; +// uint8_t num_of_source_packets = 0; +// unsigned int last_packet_size = 0; +// fec_encoder_.GetFecPacketsParams(payload_size, num_of_total_packets, +// num_of_source_packets, last_packet_size); + +// timestamp_ = std::chrono::duration_cast( +// std::chrono::system_clock::now().time_since_epoch()) +// .count(); + +// for (uint8_t index = 0; index < num_of_total_packets; index++) { +// RtpPacket rtp_packet; +// if (index < num_of_source_packets) { +// rtp_packet.SetVerion(kRtpVersion); +// rtp_packet.SetHasPadding(false); +// rtp_packet.SetHasExtension(has_extension_); +// rtp_packet.SetMarker(index == num_of_source_packets - 1 ? 1 : 0); +// rtp_packet.SetPayloadType(RtpPacket::PAYLOAD_TYPE::H264_FEC_SOURCE); +// rtp_packet.SetSequenceNumber(sequence_number_++); +// rtp_packet.SetTimestamp(timestamp_); +// rtp_packet.SetSsrc(ssrc_); + +// if (!csrcs_.empty()) { +// rtp_packet.SetCsrcs(csrcs_); +// } + +// if (has_extension_) { +// rtp_packet.SetExtensionProfile(extension_profile_); +// rtp_packet.SetExtensionData(extension_data_, extension_len_); +// } + +// RtpPacket::FU_INDICATOR fu_indicator; +// fu_indicator.forbidden_bit = 0; +// fu_indicator.nal_reference_idc = 0; +// fu_indicator.nal_unit_type = FU_A; + +// RtpPacket::FU_HEADER fu_header; +// fu_header.start = index == 0 ? 1 : 0; +// fu_header.end = index == num_of_source_packets - 1 ? 1 : 0; +// fu_header.remain_bit = 0; +// fu_header.nal_unit_type = FU_A; + +// rtp_packet.SetFuIndicator(fu_indicator); +// rtp_packet.SetFuHeader(fu_header); + +// if (index == num_of_source_packets - 1) { +// if (last_packet_size > 0) { +// rtp_packet.EncodeH264FecSource(fec_packets[index], +// last_packet_size, +// index, num_of_source_packets); +// } else { +// rtp_packet.EncodeH264FecSource(fec_packets[index], MAX_NALU_LEN, +// index, num_of_source_packets); +// } +// } else { +// rtp_packet.EncodeH264FecSource(fec_packets[index], MAX_NALU_LEN, +// index, +// num_of_source_packets); +// } + +// } else if (index >= num_of_source_packets && index < +// num_of_total_packets) { +// rtp_packet.SetVerion(kRtpVersion); +// rtp_packet.SetHasPadding(false); +// rtp_packet.SetHasExtension(has_extension_); +// rtp_packet.SetMarker(index == num_of_total_packets - 1 ? 1 : 0); +// rtp_packet.SetPayloadType(RtpPacket::PAYLOAD_TYPE::H264_FEC_REPAIR); +// rtp_packet.SetSequenceNumber(sequence_number_++); +// rtp_packet.SetTimestamp(timestamp_); +// rtp_packet.SetSsrc(ssrc_); + +// if (!csrcs_.empty()) { +// rtp_packet.SetCsrcs(csrcs_); +// } + +// if (has_extension_) { +// rtp_packet.SetExtensionProfile(extension_profile_); +// rtp_packet.SetExtensionData(extension_data_, extension_len_); +// } +// rtp_packet.EncodeH264FecRepair(fec_packets[index], MAX_NALU_LEN, index, +// num_of_source_packets); +// } +// packets.emplace_back(rtp_packet); + +// // if (index < num_of_source_packets) { +// // rtp_packet.EncodeH264Fua(fec_packets[index], MAX_NALU_LEN); +// // packets.emplace_back(rtp_packet); +// // } +// } + +// fec_encoder_.ReleaseFecPackets(fec_packets, payload_size); +// return; +// } + +// if (payload_size <= MAX_NALU_LEN) { +// RtpPacket rtp_packet; +// rtp_packet.SetVerion(kRtpVersion); +// rtp_packet.SetHasPadding(false); + +// has_extension_ = true; +// uint32_t abs_send_time = +// std::chrono::duration_cast( +// std::chrono::system_clock::now().time_since_epoch()) +// .count(); +// rtp_packet.SetAbsoluteSendTimestamp(abs_send_time); + +// rtp_packet.SetHasExtension(has_extension_); +// rtp_packet.SetMarker(1); +// rtp_packet.SetPayloadType(RtpPacket::PAYLOAD_TYPE(payload_type_)); +// rtp_packet.SetSequenceNumber(sequence_number_++); + +// timestamp_ = std::chrono::duration_cast( +// std::chrono::system_clock::now().time_since_epoch()) +// .count(); + +// rtp_packet.SetTimestamp(timestamp_); +// rtp_packet.SetSsrc(ssrc_); + +// if (!csrcs_.empty()) { +// rtp_packet.SetCsrcs(csrcs_); +// } + +// if (has_extension_) { +// rtp_packet.SetExtensionProfile(extension_profile_); +// rtp_packet.SetExtensionData(extension_data_, extension_len_); +// } + +// RtpPacket::FU_INDICATOR fu_indicator; +// fu_indicator.forbidden_bit = 0; +// fu_indicator.nal_reference_idc = 1; +// fu_indicator.nal_unit_type = NALU; +// rtp_packet.SetFuIndicator(fu_indicator); + +// rtp_packet.EncodeH264Nalu(payload, payload_size); +// packets.emplace_back(rtp_packet); + +// return true; +// } diff --git a/src/rtp/rtp_packetizer/rtp_packetizer_h264.h b/src/rtp/rtp_packetizer/rtp_packetizer_h264.h new file mode 100644 index 0000000..8b49226 --- /dev/null +++ b/src/rtp/rtp_packetizer/rtp_packetizer_h264.h @@ -0,0 +1,45 @@ +/* + * @Author: DI JUNKUN + * @Date: 2025-01-22 + * Copyright (c) 2025 by DI JUNKUN, All Rights Reserved. + */ + +#ifndef _RTP_PACKETIZER_H264_H_ +#define _RTP_PACKETIZER_H264_H_ + +#include "rtp_packetizer.h" + +class RtpPacketizerH264 : public RtpPacketizer { + public: + RtpPacketizerH264(); + + virtual ~RtpPacketizerH264(); + + std::vector Build(uint8_t* payload, + uint32_t payload_size) override; + + private: + bool RtpPacketizerH264::EncodeH264Fua(RtpPacket& rtp_packet, uint8_t* payload, + size_t payload_size); + + private: + uint8_t version_; + bool has_padding_; + bool has_extension_; + uint32_t csrc_count_; + bool marker_; + uint32_t payload_type_; + uint16_t sequence_number_; + uint64_t timestamp_; + uint32_t ssrc_; + std::vector csrcs_; + uint16_t profile_; + uint16_t extension_profile_; + uint16_t extension_len_; + uint8_t* extension_data_; + + private: + std::vector rtp_packet_frame_; +}; + +#endif \ No newline at end of file