mirror of
https://github.com/kunkundi/crossdesk.git
synced 2025-10-26 20:25:34 +08:00
[feat] use the io statistics module to collect network information
This commit is contained in:
85
src/rtp/rtp_packet/byte_buffer.cpp
Normal file
85
src/rtp/rtp_packet/byte_buffer.cpp
Normal file
@@ -0,0 +1,85 @@
|
||||
#include "byte_buffer.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
ByteBufferReader::ByteBufferReader(const char* bytes, size_t len) {
|
||||
Construct(bytes, len);
|
||||
}
|
||||
|
||||
void ByteBufferReader::Construct(const char* bytes, size_t len) {
|
||||
bytes_ = bytes;
|
||||
size_ = len;
|
||||
start_ = 0;
|
||||
end_ = len;
|
||||
}
|
||||
|
||||
bool ByteBufferReader::ReadBytes(char* val, size_t len) {
|
||||
if (len > Length()) {
|
||||
return false;
|
||||
} else {
|
||||
memcpy(val, bytes_ + start_, len);
|
||||
start_ += len;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool ByteBufferReader::ReadUInt8(uint8_t* val) {
|
||||
if (!val) return false;
|
||||
|
||||
return ReadBytes(reinterpret_cast<char*>(val), 1);
|
||||
}
|
||||
|
||||
bool ByteBufferReader::ReadUVarint(uint64_t* val) {
|
||||
if (!val) {
|
||||
return false;
|
||||
}
|
||||
// Integers are deserialized 7 bits at a time, with each byte having a
|
||||
// continuation byte (msb=1) if there are more bytes to be read.
|
||||
uint64_t v = 0;
|
||||
for (int i = 0; i < 64; i += 7) {
|
||||
char byte;
|
||||
if (!ReadBytes(&byte, 1)) {
|
||||
return false;
|
||||
}
|
||||
// Read the first 7 bits of the byte, then offset by bits read so far.
|
||||
v |= (static_cast<uint64_t>(byte) & 0x7F) << i;
|
||||
// True if the msb is not a continuation byte.
|
||||
if (static_cast<uint64_t>(byte) < 0x80) {
|
||||
*val = v;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ByteBufferReader::ReadUVarint(uint64_t* val, size_t* len) {
|
||||
if (!val) {
|
||||
return false;
|
||||
}
|
||||
// Integers are deserialized 7 bits at a time, with each byte having a
|
||||
// continuation byte (msb=1) if there are more bytes to be read.
|
||||
uint64_t v = 0;
|
||||
for (int i = 0; i < 64; i += 7) {
|
||||
char byte;
|
||||
if (!ReadBytes(&byte, 1)) {
|
||||
return false;
|
||||
}
|
||||
// Read the first 7 bits of the byte, then offset by bits read so far.
|
||||
v |= (static_cast<uint64_t>(byte) & 0x7F) << i;
|
||||
// True if the msb is not a continuation byte.
|
||||
if (static_cast<uint64_t>(byte) < 0x80) {
|
||||
*val = v;
|
||||
if (len) {
|
||||
*len = i / 8 + (i % 8 ? 1 : 0) + 1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ByteBufferReader::Consume(size_t size) {
|
||||
if (size > Length()) return false;
|
||||
start_ += size;
|
||||
return true;
|
||||
}
|
||||
41
src/rtp/rtp_packet/byte_buffer.h
Normal file
41
src/rtp/rtp_packet/byte_buffer.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* @Author: DI JUNKUN
|
||||
* @Date: 2024-04-22
|
||||
* Copyright (c) 2024 by DI JUNKUN, All Rights Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _BYTE_BUFFER_H_
|
||||
#define _BYTE_BUFFER_H_
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
class ByteBufferReader {
|
||||
public:
|
||||
ByteBufferReader(const char* bytes, size_t len);
|
||||
|
||||
ByteBufferReader(const ByteBufferReader&) = delete;
|
||||
ByteBufferReader& operator=(const ByteBufferReader&) = delete;
|
||||
|
||||
// Returns start of unprocessed data.
|
||||
const char* Data() const { return bytes_ + start_; }
|
||||
// Returns number of unprocessed bytes.
|
||||
size_t Length() const { return end_ - start_; }
|
||||
|
||||
bool ReadBytes(char* val, size_t len);
|
||||
bool ReadUInt8(uint8_t* val);
|
||||
bool ReadUVarint(uint64_t* val);
|
||||
bool ReadUVarint(uint64_t* val, size_t* len);
|
||||
|
||||
bool Consume(size_t size);
|
||||
|
||||
protected:
|
||||
void Construct(const char* bytes, size_t size);
|
||||
|
||||
const char* bytes_;
|
||||
size_t size_;
|
||||
size_t start_;
|
||||
size_t end_;
|
||||
};
|
||||
|
||||
#endif
|
||||
1
src/rtp/rtp_packet/obu.cpp
Normal file
1
src/rtp/rtp_packet/obu.cpp
Normal file
@@ -0,0 +1 @@
|
||||
#include "obu.h"
|
||||
49
src/rtp/rtp_packet/obu.h
Normal file
49
src/rtp/rtp_packet/obu.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* @Author: DI JUNKUN
|
||||
* @Date: 2024-04-22
|
||||
* Copyright (c) 2024 by DI JUNKUN, All Rights Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _OBU_H_
|
||||
#define _OBU_H_
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
namespace obu {
|
||||
struct PayloadSizeLimits {
|
||||
int max_payload_len = 1200;
|
||||
int first_packet_reduction_len = 0;
|
||||
int last_packet_reduction_len = 0;
|
||||
// Reduction len for packet that is first & last at the same time.
|
||||
int single_packet_reduction_len = 0;
|
||||
};
|
||||
|
||||
enum class VideoFrameType {
|
||||
kEmptyFrame = 0,
|
||||
kVideoFrameKey = 3,
|
||||
kVideoFrameDelta = 4,
|
||||
};
|
||||
|
||||
struct Obu {
|
||||
uint8_t header;
|
||||
uint8_t extension_header; // undefined if (header & kXbit) == 0
|
||||
std::vector<uint8_t> payload;
|
||||
size_t size; // size of the header and payload combined.
|
||||
};
|
||||
|
||||
struct Packet {
|
||||
explicit Packet(int first_obu_index) : first_obu(first_obu_index) {}
|
||||
// Indexes into obus_ vector of the first and last obus that should put into
|
||||
// the packet.
|
||||
int first_obu;
|
||||
int num_obu_elements = 0;
|
||||
int first_obu_offset = 0;
|
||||
int last_obu_size;
|
||||
// Total size consumed by the packet.
|
||||
int packet_size = 0;
|
||||
};
|
||||
} // namespace obu
|
||||
|
||||
#endif
|
||||
126
src/rtp/rtp_packet/obu_parser.cpp
Normal file
126
src/rtp/rtp_packet/obu_parser.cpp
Normal file
@@ -0,0 +1,126 @@
|
||||
#include "obu_parser.h"
|
||||
|
||||
#include "byte_buffer.h"
|
||||
#include "log.h"
|
||||
namespace obu {
|
||||
|
||||
constexpr int kAggregationHeaderSize = 1;
|
||||
// when there are 3 or less OBU (fragments) in a packet, size of the last one
|
||||
// can be omited.
|
||||
constexpr int kMaxNumObusToOmitSize = 3;
|
||||
constexpr uint8_t kObuSizePresentBit = 0b0'0000'010;
|
||||
constexpr int kObuTypeSequenceHeader = 1;
|
||||
constexpr int kObuTypeTemporalDelimiter = 2;
|
||||
constexpr int kObuTypeTileList = 8;
|
||||
constexpr int kObuTypePadding = 15;
|
||||
|
||||
const char* ObuTypeToString(OBU_TYPE type) {
|
||||
switch (type) {
|
||||
case OBU_SEQUENCE_HEADER:
|
||||
return "OBU_SEQUENCE_HEADER";
|
||||
case OBU_TEMPORAL_DELIMITER:
|
||||
return "OBU_TEMPORAL_DELIMITER";
|
||||
case OBU_FRAME_HEADER:
|
||||
return "OBU_FRAME_HEADER";
|
||||
case OBU_REDUNDANT_FRAME_HEADER:
|
||||
return "OBU_REDUNDANT_FRAME_HEADER";
|
||||
case OBU_FRAME:
|
||||
return "OBU_FRAME";
|
||||
case OBU_TILE_GROUP:
|
||||
return "OBU_TILE_GROUP";
|
||||
case OBU_METADATA:
|
||||
return "OBU_METADATA";
|
||||
case OBU_TILE_LIST:
|
||||
return "OBU_TILE_LIST";
|
||||
case OBU_PADDING:
|
||||
return "OBU_PADDING";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return "<Invalid OBU Type>";
|
||||
}
|
||||
|
||||
bool ObuHasExtension(uint8_t obu_header) { return obu_header & 0b0'0000'100; }
|
||||
|
||||
bool ObuHasSize(uint8_t obu_header) { return obu_header & kObuSizePresentBit; }
|
||||
|
||||
int ObuType(uint8_t obu_header) { return (obu_header & 0b0'1111'000) >> 3; }
|
||||
|
||||
std::vector<Obu> ParseObus(uint8_t* payload, int payload_size) {
|
||||
std::vector<Obu> result;
|
||||
ByteBufferReader payload_reader(reinterpret_cast<const char*>(payload),
|
||||
payload_size);
|
||||
while (payload_reader.Length() > 0) {
|
||||
Obu obu;
|
||||
bool has_ext_header = false;
|
||||
payload_reader.ReadUInt8(&obu.header);
|
||||
obu.size = 1;
|
||||
if (ObuHasExtension(obu.header)) {
|
||||
if (payload_reader.Length() == 0) {
|
||||
LOG_ERROR(
|
||||
"Malformed AV1 input: expected extension_header, no more bytes in "
|
||||
"the buffer. Offset: {}",
|
||||
(payload_size - payload_reader.Length()));
|
||||
return {};
|
||||
}
|
||||
payload_reader.ReadUInt8(&obu.extension_header);
|
||||
++obu.size;
|
||||
has_ext_header = true;
|
||||
}
|
||||
if (!ObuHasSize(obu.header)) {
|
||||
obu.payload = std::vector<uint8_t>(
|
||||
reinterpret_cast<const uint8_t*>(payload_reader.Data()),
|
||||
reinterpret_cast<const uint8_t*>(payload_reader.Data()) +
|
||||
payload_reader.Length());
|
||||
payload_reader.Consume(payload_reader.Length());
|
||||
} else {
|
||||
uint64_t size = 0;
|
||||
size_t size_len = 0;
|
||||
if (!payload_reader.ReadUVarint(&size, &size_len) ||
|
||||
size > payload_reader.Length()) {
|
||||
LOG_ERROR(
|
||||
"Malformed AV1 input: declared payload_size {} is larger than "
|
||||
"remaining buffer size {}",
|
||||
size, payload_reader.Length());
|
||||
return {};
|
||||
}
|
||||
if (0 == size) {
|
||||
obu.payload.push_back(0);
|
||||
} else {
|
||||
obu.payload = std::vector<uint8_t>(
|
||||
reinterpret_cast<const uint8_t*>(payload_reader.Data()),
|
||||
reinterpret_cast<const uint8_t*>(payload_reader.Data()) + size);
|
||||
|
||||
std::vector<uint8_t> size_data = std::vector<uint8_t>(
|
||||
reinterpret_cast<const uint8_t*>(payload_reader.Data() - size_len),
|
||||
reinterpret_cast<const uint8_t*>(payload_reader.Data() - size_len) +
|
||||
size_len);
|
||||
obu.payload.insert(obu.payload.begin(), size_data.begin(),
|
||||
size_data.end());
|
||||
}
|
||||
payload_reader.Consume(size);
|
||||
}
|
||||
obu.size += obu.payload.size();
|
||||
if (has_ext_header) {
|
||||
obu.payload.insert(obu.payload.begin(), obu.extension_header);
|
||||
}
|
||||
// Skip obus that shouldn't be transfered over rtp.
|
||||
// int obu_type = ObuType(obu.header);
|
||||
obu.payload.insert(obu.payload.begin(), obu.header);
|
||||
// if (obu_type != kObuTypeTemporalDelimiter && //
|
||||
// obu_type != kObuTypeTileList && //
|
||||
// obu_type != kObuTypePadding) {
|
||||
result.push_back(obu);
|
||||
// }
|
||||
}
|
||||
|
||||
// for (int i = 0; i < result.size(); i++) {
|
||||
// LOG_ERROR("[{}] Obu size = [{}], Obu type [{}|{}]", i, result[i].size,
|
||||
// ObuType(result[i].payload[0]),
|
||||
// ObuTypeToString((OBU_TYPE)ObuType(result[i].header)));
|
||||
// }
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace obu
|
||||
46
src/rtp/rtp_packet/obu_parser.h
Normal file
46
src/rtp/rtp_packet/obu_parser.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* @Author: DI JUNKUN
|
||||
* @Date: 2024-04-22
|
||||
* Copyright (c) 2024 by DI JUNKUN, All Rights Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _OBU_PARSER_H_
|
||||
#define _OBU_PARSER_H_
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
#include "obu.h"
|
||||
#include "rtp_packet.h"
|
||||
|
||||
namespace obu {
|
||||
|
||||
typedef enum {
|
||||
OBU_SEQUENCE_HEADER = 1,
|
||||
OBU_TEMPORAL_DELIMITER = 2,
|
||||
OBU_FRAME_HEADER = 3,
|
||||
OBU_TILE_GROUP = 4,
|
||||
OBU_METADATA = 5,
|
||||
OBU_FRAME = 6,
|
||||
OBU_REDUNDANT_FRAME_HEADER = 7,
|
||||
OBU_TILE_LIST = 8,
|
||||
OBU_PADDING = 15,
|
||||
} OBU_TYPE;
|
||||
|
||||
std::vector<Obu> ParseObus(uint8_t* payload, int payload_size);
|
||||
|
||||
std::vector<Packet> Packetize(std::vector<Obu> obus);
|
||||
|
||||
bool NextPacket(RtpPacket* packet);
|
||||
|
||||
const char* ObuTypeToString(OBU_TYPE type);
|
||||
|
||||
bool ObuHasExtension(uint8_t obu_header);
|
||||
|
||||
bool ObuHasSize(uint8_t obu_header);
|
||||
|
||||
int ObuType(uint8_t obu_header);
|
||||
} // namespace obu
|
||||
|
||||
#endif
|
||||
626
src/rtp/rtp_packet/rtp_codec.cpp
Normal file
626
src/rtp/rtp_packet/rtp_codec.cpp
Normal file
@@ -0,0 +1,626 @@
|
||||
#include "rtp_codec.h"
|
||||
|
||||
#include <chrono>
|
||||
|
||||
#include "log.h"
|
||||
#include "obu_parser.h"
|
||||
|
||||
#define RTP_VERSION 2
|
||||
#define NALU 1
|
||||
#define FU_A 28
|
||||
#define FU_B 29
|
||||
|
||||
constexpr int kObuTypeSequenceHeader = 1;
|
||||
|
||||
using namespace obu;
|
||||
|
||||
RtpCodec ::RtpCodec(RtpPacket::PAYLOAD_TYPE payload_type)
|
||||
: version_(RTP_VERSION),
|
||||
has_padding_(false),
|
||||
has_extension_(false),
|
||||
payload_type_(payload_type),
|
||||
sequence_number_(1) {
|
||||
fec_encoder_.Init();
|
||||
}
|
||||
|
||||
RtpCodec ::~RtpCodec() {
|
||||
if (extension_data_) {
|
||||
delete extension_data_;
|
||||
extension_data_ = nullptr;
|
||||
}
|
||||
|
||||
// if (rtp_packet_) {
|
||||
// delete rtp_packet_;
|
||||
// rtp_packet_ = nullptr;
|
||||
// }
|
||||
}
|
||||
|
||||
void RtpCodec::Encode(uint8_t* buffer, uint32_t size,
|
||||
std::vector<RtpPacket>& packets) {
|
||||
if (RtpPacket::PAYLOAD_TYPE::H264 == payload_type_) {
|
||||
if (fec_enable_ && IsKeyFrame((const uint8_t*)buffer, size)) {
|
||||
uint8_t** fec_packets = fec_encoder_.Encode((const char*)buffer, 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(size, num_of_total_packets,
|
||||
num_of_source_packets, last_packet_size);
|
||||
|
||||
timestamp_ = std::chrono::duration_cast<std::chrono::microseconds>(
|
||||
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(version_);
|
||||
rtp_packet.SetHasPadding(has_padding_);
|
||||
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(version_);
|
||||
rtp_packet.SetHasPadding(has_padding_);
|
||||
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, size);
|
||||
return;
|
||||
}
|
||||
if (size <= MAX_NALU_LEN) {
|
||||
RtpPacket rtp_packet;
|
||||
rtp_packet.SetVerion(version_);
|
||||
rtp_packet.SetHasPadding(has_padding_);
|
||||
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::microseconds>(
|
||||
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(buffer, size);
|
||||
packets.emplace_back(rtp_packet);
|
||||
|
||||
} else {
|
||||
uint32_t last_packet_size = size % MAX_NALU_LEN;
|
||||
uint32_t packet_num = size / MAX_NALU_LEN + (last_packet_size ? 1 : 0);
|
||||
timestamp_ = std::chrono::duration_cast<std::chrono::microseconds>(
|
||||
std::chrono::system_clock::now().time_since_epoch())
|
||||
.count();
|
||||
|
||||
for (uint32_t index = 0; index < packet_num; index++) {
|
||||
RtpPacket rtp_packet;
|
||||
rtp_packet.SetVerion(version_);
|
||||
rtp_packet.SetHasPadding(has_padding_);
|
||||
rtp_packet.SetHasExtension(has_extension_);
|
||||
rtp_packet.SetMarker(index == packet_num - 1 ? 1 : 0);
|
||||
rtp_packet.SetPayloadType(RtpPacket::PAYLOAD_TYPE(payload_type_));
|
||||
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 == packet_num - 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 == packet_num - 1 && last_packet_size > 0) {
|
||||
rtp_packet.EncodeH264Fua(buffer + index * MAX_NALU_LEN,
|
||||
last_packet_size);
|
||||
} else {
|
||||
rtp_packet.EncodeH264Fua(buffer + index * MAX_NALU_LEN, MAX_NALU_LEN);
|
||||
}
|
||||
packets.emplace_back(rtp_packet);
|
||||
}
|
||||
}
|
||||
} else if (RtpPacket::PAYLOAD_TYPE::AV1 == payload_type_) {
|
||||
std::vector<Obu> obus = ParseObus(buffer, size);
|
||||
LOG_ERROR("Total size = [{}]", size);
|
||||
for (int i = 0; i < obus.size(); i++) {
|
||||
LOG_ERROR("[{}] Obu size = [{}], Obu type [{}]", i, obus[i].size,
|
||||
ObuTypeToString((OBU_TYPE)ObuType(obus[i].header)));
|
||||
if (obus[i].size <= MAX_NALU_LEN) {
|
||||
RtpPacket rtp_packet;
|
||||
rtp_packet.SetVerion(version_);
|
||||
rtp_packet.SetHasPadding(has_padding_);
|
||||
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::microseconds>(
|
||||
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_);
|
||||
}
|
||||
|
||||
rtp_packet.SetAv1AggrHeader(0, 0, 1, 0);
|
||||
|
||||
rtp_packet.EncodeAv1(obus[i].payload.data(), obus[i].payload.size());
|
||||
packets.emplace_back(rtp_packet);
|
||||
} else {
|
||||
uint32_t last_packet_size = obus[i].payload.size() % MAX_NALU_LEN;
|
||||
size_t packet_num =
|
||||
obus[i].payload.size() / MAX_NALU_LEN + (last_packet_size ? 1 : 0);
|
||||
timestamp_ = std::chrono::duration_cast<std::chrono::microseconds>(
|
||||
std::chrono::system_clock::now().time_since_epoch())
|
||||
.count();
|
||||
for (uint32_t index = 0; index < packet_num; index++) {
|
||||
RtpPacket rtp_packet;
|
||||
rtp_packet.SetVerion(version_);
|
||||
rtp_packet.SetHasPadding(has_padding_);
|
||||
rtp_packet.SetHasExtension(has_extension_);
|
||||
rtp_packet.SetMarker(index == packet_num - 1 ? 1 : 0);
|
||||
rtp_packet.SetPayloadType(RtpPacket::PAYLOAD_TYPE(payload_type_));
|
||||
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_);
|
||||
}
|
||||
|
||||
int z = index != 0 ? 1 : 0;
|
||||
int y = index != packet_num - 1 ? 1 : 0;
|
||||
int w = 1;
|
||||
int n = 0;
|
||||
rtp_packet.SetAv1AggrHeader(z, y, w, n);
|
||||
|
||||
if (index == packet_num - 1 && last_packet_size > 0) {
|
||||
rtp_packet.EncodeAv1(obus[i].payload.data() + index * MAX_NALU_LEN,
|
||||
last_packet_size);
|
||||
} else {
|
||||
rtp_packet.EncodeAv1(obus[i].payload.data() + index * MAX_NALU_LEN,
|
||||
MAX_NALU_LEN);
|
||||
}
|
||||
packets.emplace_back(rtp_packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (RtpPacket::PAYLOAD_TYPE::OPUS == payload_type_) {
|
||||
RtpPacket rtp_packet;
|
||||
rtp_packet.SetVerion(version_);
|
||||
rtp_packet.SetHasPadding(has_padding_);
|
||||
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::microseconds>(
|
||||
std::chrono::system_clock::now().time_since_epoch())
|
||||
.count();
|
||||
rtp_packet.SetTimestamp(timestamp_);
|
||||
rtp_packet.SetSsrc(ssrc_);
|
||||
|
||||
rtp_packet.Encode(buffer, size);
|
||||
packets.emplace_back(rtp_packet);
|
||||
} else if (RtpPacket::PAYLOAD_TYPE::DATA == payload_type_) {
|
||||
RtpPacket rtp_packet;
|
||||
rtp_packet.SetVerion(version_);
|
||||
rtp_packet.SetHasPadding(has_padding_);
|
||||
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::microseconds>(
|
||||
std::chrono::system_clock::now().time_since_epoch())
|
||||
.count();
|
||||
rtp_packet.SetTimestamp(timestamp_);
|
||||
rtp_packet.SetSsrc(ssrc_);
|
||||
|
||||
rtp_packet.Encode(buffer, size);
|
||||
packets.emplace_back(rtp_packet);
|
||||
}
|
||||
}
|
||||
|
||||
void RtpCodec::Encode(VideoFrameType frame_type, uint8_t* buffer, uint32_t size,
|
||||
std::vector<RtpPacket>& packets) {
|
||||
if (RtpPacket::PAYLOAD_TYPE::H264 == payload_type_) {
|
||||
if (fec_enable_ && IsKeyFrame((const uint8_t*)buffer, size)) {
|
||||
uint8_t** fec_packets = fec_encoder_.Encode((const char*)buffer, 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(size, num_of_total_packets,
|
||||
num_of_source_packets, last_packet_size);
|
||||
|
||||
timestamp_ = std::chrono::duration_cast<std::chrono::microseconds>(
|
||||
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(version_);
|
||||
rtp_packet.SetHasPadding(has_padding_);
|
||||
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(version_);
|
||||
rtp_packet.SetHasPadding(has_padding_);
|
||||
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, size);
|
||||
return;
|
||||
}
|
||||
|
||||
if (size <= MAX_NALU_LEN) {
|
||||
RtpPacket rtp_packet;
|
||||
rtp_packet.SetVerion(version_);
|
||||
rtp_packet.SetHasPadding(has_padding_);
|
||||
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::microseconds>(
|
||||
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(buffer, size);
|
||||
packets.emplace_back(rtp_packet);
|
||||
|
||||
} else {
|
||||
uint32_t last_packet_size = size % MAX_NALU_LEN;
|
||||
uint32_t packet_num = size / MAX_NALU_LEN + (last_packet_size ? 1 : 0);
|
||||
timestamp_ = std::chrono::duration_cast<std::chrono::microseconds>(
|
||||
std::chrono::system_clock::now().time_since_epoch())
|
||||
.count();
|
||||
|
||||
for (uint32_t index = 0; index < packet_num; index++) {
|
||||
RtpPacket rtp_packet;
|
||||
rtp_packet.SetVerion(version_);
|
||||
rtp_packet.SetHasPadding(has_padding_);
|
||||
rtp_packet.SetHasExtension(has_extension_);
|
||||
rtp_packet.SetMarker(index == packet_num - 1 ? 1 : 0);
|
||||
rtp_packet.SetPayloadType(RtpPacket::PAYLOAD_TYPE(payload_type_));
|
||||
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 == packet_num - 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 == packet_num - 1 && last_packet_size > 0) {
|
||||
rtp_packet.EncodeH264Fua(buffer + index * MAX_NALU_LEN,
|
||||
last_packet_size);
|
||||
} else {
|
||||
rtp_packet.EncodeH264Fua(buffer + index * MAX_NALU_LEN, MAX_NALU_LEN);
|
||||
}
|
||||
packets.emplace_back(rtp_packet);
|
||||
}
|
||||
}
|
||||
} else if (RtpPacket::PAYLOAD_TYPE::AV1 == payload_type_) {
|
||||
std::vector<Obu> obus = ParseObus(buffer, size);
|
||||
uint64_t timestamp =
|
||||
std::chrono::duration_cast<std::chrono::microseconds>(
|
||||
std::chrono::system_clock::now().time_since_epoch())
|
||||
.count();
|
||||
|
||||
for (int i = 0; i < obus.size(); i++) {
|
||||
if (obus[i].size <= MAX_NALU_LEN) {
|
||||
RtpPacket rtp_packet;
|
||||
rtp_packet.SetVerion(version_);
|
||||
rtp_packet.SetHasPadding(has_padding_);
|
||||
rtp_packet.SetHasExtension(has_extension_);
|
||||
rtp_packet.SetMarker(1);
|
||||
rtp_packet.SetPayloadType(RtpPacket::PAYLOAD_TYPE(payload_type_));
|
||||
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.SetAv1AggrHeader(0, 0, 1, 0);
|
||||
rtp_packet.EncodeAv1(obus[i].payload.data(), obus[i].size);
|
||||
packets.emplace_back(rtp_packet);
|
||||
} else {
|
||||
uint32_t last_packet_size = obus[i].size % MAX_NALU_LEN;
|
||||
size_t packet_num =
|
||||
obus[i].size / MAX_NALU_LEN + (last_packet_size ? 1 : 0);
|
||||
|
||||
for (uint32_t index = 0; index < packet_num; index++) {
|
||||
RtpPacket rtp_packet;
|
||||
rtp_packet.SetVerion(version_);
|
||||
rtp_packet.SetHasPadding(has_padding_);
|
||||
rtp_packet.SetHasExtension(has_extension_);
|
||||
rtp_packet.SetMarker(index == packet_num - 1 ? 1 : 0);
|
||||
rtp_packet.SetPayloadType(RtpPacket::PAYLOAD_TYPE(payload_type_));
|
||||
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_);
|
||||
}
|
||||
|
||||
int z = index != 0 ? 1 : 0;
|
||||
int y = index != packet_num - 1 ? 1 : 0;
|
||||
int w = 1;
|
||||
int n = (frame_type == VideoFrameType::kVideoFrameKey) &&
|
||||
(ObuType(obus[i].header) == kObuTypeSequenceHeader)
|
||||
? 1
|
||||
: 0;
|
||||
rtp_packet.SetAv1AggrHeader(z, y, w, n);
|
||||
if (index == packet_num - 1 && last_packet_size > 0) {
|
||||
rtp_packet.EncodeAv1(obus[i].payload.data() + index * MAX_NALU_LEN,
|
||||
last_packet_size);
|
||||
} else {
|
||||
rtp_packet.EncodeAv1(obus[i].payload.data() + index * MAX_NALU_LEN,
|
||||
MAX_NALU_LEN);
|
||||
}
|
||||
|
||||
packets.emplace_back(rtp_packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t RtpCodec::Decode(RtpPacket& packet, uint8_t* payload) {
|
||||
// if ((packet.Buffer()[13] >> 6) & 0x01) {
|
||||
// LOG_ERROR("End bit!!!!!!!!!!!!!!!");
|
||||
// }
|
||||
|
||||
// if ((packet.Buffer()[13] >> 7) & 0x01) {
|
||||
// LOG_ERROR("Start bit!!!!!!!!!!!!!!!");
|
||||
// }
|
||||
|
||||
auto nal_unit_type = packet.Buffer()[12] & 0x1F;
|
||||
|
||||
if (NALU == nal_unit_type) {
|
||||
LOG_ERROR("Nalu");
|
||||
return packet.DecodeH264Nalu(payload);
|
||||
} else if (FU_A == nal_unit_type) {
|
||||
LOG_ERROR("Fua");
|
||||
return packet.DecodeH264Fua(payload);
|
||||
} else {
|
||||
LOG_ERROR("Default");
|
||||
return packet.DecodeData(payload);
|
||||
}
|
||||
}
|
||||
|
||||
bool RtpCodec::IsKeyFrame(const uint8_t* buffer, uint32_t size) {
|
||||
if (buffer != nullptr && size != 0 && (*(buffer + 4) & 0x1f) == 0x07) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
60
src/rtp/rtp_packet/rtp_codec.h
Normal file
60
src/rtp/rtp_packet/rtp_codec.h
Normal file
@@ -0,0 +1,60 @@
|
||||
#ifndef _RTP_CODEC_H_
|
||||
#define _RTP_CODEC_H_
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
#include "fec_encoder.h"
|
||||
#include "rtp_packet.h"
|
||||
|
||||
class RtpCodec {
|
||||
public:
|
||||
enum VideoFrameType {
|
||||
kEmptyFrame = 0,
|
||||
kVideoFrameKey = 3,
|
||||
kVideoFrameDelta = 4,
|
||||
};
|
||||
|
||||
public:
|
||||
RtpCodec(RtpPacket::PAYLOAD_TYPE payload_type);
|
||||
~RtpCodec();
|
||||
|
||||
public:
|
||||
void Encode(uint8_t* buffer, uint32_t size, std::vector<RtpPacket>& packets);
|
||||
void Encode(VideoFrameType frame_type, uint8_t* buffer, uint32_t size,
|
||||
std::vector<RtpPacket>& packets);
|
||||
size_t Decode(RtpPacket& packet, uint8_t* payload);
|
||||
|
||||
// protected:
|
||||
// void OnReceiveFrame(uint8_t* payload) = 0;
|
||||
private:
|
||||
bool IsKeyFrame(const uint8_t* buffer, uint32_t size);
|
||||
|
||||
void EncodeAv1(uint8_t* buffer, uint32_t size,
|
||||
std::vector<RtpPacket>& packets);
|
||||
|
||||
private:
|
||||
uint8_t version_ = 0;
|
||||
bool has_padding_ = false;
|
||||
bool has_extension_ = false;
|
||||
uint32_t total_csrc_number_ = 0;
|
||||
bool marker_ = false;
|
||||
uint32_t payload_type_ = 0;
|
||||
uint16_t sequence_number_ = 0;
|
||||
uint64_t timestamp_ = 0;
|
||||
uint32_t ssrc_ = 0;
|
||||
std::vector<uint32_t> csrcs_;
|
||||
uint16_t profile_ = 0;
|
||||
uint16_t extension_profile_ = 0;
|
||||
uint16_t extension_len_ = 0;
|
||||
uint8_t* extension_data_ = nullptr;
|
||||
|
||||
private:
|
||||
// RtpPacket* rtp_packet_ = nullptr;
|
||||
RtpPacket::FU_INDICATOR fu_indicator_;
|
||||
bool fec_enable_ = false;
|
||||
FecEncoder fec_encoder_;
|
||||
};
|
||||
|
||||
#endif
|
||||
94
src/rtp/rtp_packet/rtp_codec_av1.cpp
Normal file
94
src/rtp/rtp_packet/rtp_codec_av1.cpp
Normal file
@@ -0,0 +1,94 @@
|
||||
#include "byte_buffer.h"
|
||||
#include "log.h"
|
||||
#include "obu_parser.h"
|
||||
#include "rtp_codec.h"
|
||||
|
||||
// void EncodeAv1(uint8_t* buffer, size_t size, std::vector<RtpPacket>& packets)
|
||||
// {
|
||||
// std::vector<Obu> obus = obu::ParseObus(buffer, size);
|
||||
// std::vector<Packet> packets = obu::Packetizer(obus);
|
||||
|
||||
// int num_packets = packets.size();
|
||||
|
||||
// if (1 == num_packets) {
|
||||
// }
|
||||
|
||||
// // LOG_ERROR("Total size = [{}]", size);
|
||||
|
||||
// uint32_t timestamp = std::chrono::duration_cast<std::chrono::microseconds>(
|
||||
// std::chrono::system_clock::now().time_since_epoch())
|
||||
// .count();
|
||||
|
||||
// for (int i = 0; i < obus.size(); i++) {
|
||||
// // LOG_ERROR("1 [{}] Obu size = [{}], Obu type [{}]", i, obus[i].size_,
|
||||
// // ObuTypeToString((OBU_TYPE)ObuType(obus[i].header_)));
|
||||
|
||||
// if (obus[i].size_ <= MAX_NALU_LEN) {
|
||||
// RtpPacket rtp_packet;
|
||||
// rtp_packet.SetVerion(version_);
|
||||
// rtp_packet.SetHasPadding(has_padding_);
|
||||
// rtp_packet.SetHasExtension(has_extension_);
|
||||
// rtp_packet.SetMarker(1);
|
||||
// rtp_packet.SetPayloadType(RtpPacket::PAYLOAD_TYPE(payload_type_));
|
||||
// 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.SetAv1AggrHeader(0, 0, 1, 0);
|
||||
// rtp_packet.EncodeAv1(obus[i].data_, obus[i].size_);
|
||||
|
||||
// packets.emplace_back(rtp_packet);
|
||||
// } else {
|
||||
// size_t last_packet_size = obus[i].size_ % MAX_NALU_LEN;
|
||||
// size_t packet_num =
|
||||
// obus[i].size_ / MAX_NALU_LEN + (last_packet_size ? 1 : 0);
|
||||
|
||||
// for (size_t index = 0; index < packet_num; index++) {
|
||||
// RtpPacket rtp_packet;
|
||||
// rtp_packet.SetVerion(version_);
|
||||
// rtp_packet.SetHasPadding(has_padding_);
|
||||
// rtp_packet.SetHasExtension(has_extension_);
|
||||
// rtp_packet.SetMarker(index == packet_num - 1 ? 1 : 0);
|
||||
// rtp_packet.SetPayloadType(RtpPacket::PAYLOAD_TYPE(payload_type_));
|
||||
// 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_);
|
||||
// }
|
||||
|
||||
// int z = index != 0 ? 1 : 0;
|
||||
// int y = index != packet_num - 1 ? 1 : 0;
|
||||
// int w = 1;
|
||||
// int n = (frame_type == VideoFrameType::kVideoFrameKey) &&
|
||||
// (ObuType(obus[i].header_) == kObuTypeSequenceHeader)
|
||||
// ? 1
|
||||
// : 0;
|
||||
// rtp_packet.SetAv1AggrHeader(z, y, w, n);
|
||||
|
||||
// if (index == packet_num - 1 && last_packet_size > 0) {
|
||||
// rtp_packet.EncodeAv1(obus[i].data_ + index * MAX_NALU_LEN,
|
||||
// last_packet_size);
|
||||
// } else {
|
||||
// rtp_packet.EncodeAv1(obus[i].data_ + index * MAX_NALU_LEN,
|
||||
// MAX_NALU_LEN);
|
||||
// }
|
||||
|
||||
// packets.emplace_back(rtp_packet);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
771
src/rtp/rtp_packet/rtp_packet.cpp
Normal file
771
src/rtp/rtp_packet/rtp_packet.cpp
Normal file
@@ -0,0 +1,771 @@
|
||||
#include "rtp_packet.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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_);
|
||||
}
|
||||
}
|
||||
|
||||
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_);
|
||||
}
|
||||
}
|
||||
|
||||
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_);
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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) |
|
||||
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];
|
||||
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;
|
||||
|
||||
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;
|
||||
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;
|
||||
|
||||
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_;
|
||||
}
|
||||
432
src/rtp/rtp_packet/rtp_packet.h
Normal file
432
src/rtp/rtp_packet/rtp_packet.h
Normal file
@@ -0,0 +1,432 @@
|
||||
#ifndef _RTP_PACKET_H_
|
||||
#define _RTP_PACKET_H_
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
|
||||
#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(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);
|
||||
|
||||
~RtpPacket();
|
||||
|
||||
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<uint32_t> &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_);
|
||||
}
|
||||
|
||||
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() {
|
||||
ParseRtpData();
|
||||
return version_;
|
||||
}
|
||||
bool HasPadding() {
|
||||
ParseRtpData();
|
||||
return has_padding_;
|
||||
}
|
||||
bool HasExtension() {
|
||||
ParseRtpData();
|
||||
return has_extension_;
|
||||
}
|
||||
bool Marker() {
|
||||
ParseRtpData();
|
||||
return marker_;
|
||||
}
|
||||
PAYLOAD_TYPE PayloadType() {
|
||||
ParseRtpData();
|
||||
return PAYLOAD_TYPE(payload_type_);
|
||||
}
|
||||
uint16_t SequenceNumber() {
|
||||
ParseRtpData();
|
||||
return sequence_number_;
|
||||
}
|
||||
uint64_t Timestamp() {
|
||||
ParseRtpData();
|
||||
return timestamp_;
|
||||
}
|
||||
uint32_t Ssrc() {
|
||||
ParseRtpData();
|
||||
return ssrc_;
|
||||
}
|
||||
std::vector<uint32_t> Csrcs() {
|
||||
ParseRtpData();
|
||||
return csrcs_;
|
||||
};
|
||||
uint16_t ExtensionProfile() {
|
||||
ParseRtpData();
|
||||
return extension_profile_;
|
||||
}
|
||||
const uint8_t *ExtensionData() {
|
||||
ParseRtpData();
|
||||
return extension_data_;
|
||||
}
|
||||
|
||||
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_;
|
||||
}
|
||||
|
||||
// Entire RTP buffer
|
||||
const uint8_t *Buffer() const { return buffer_; }
|
||||
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 total_csrc_number_ = 0;
|
||||
bool marker_ = false;
|
||||
uint8_t payload_type_ = 0;
|
||||
uint16_t sequence_number_ = 1;
|
||||
uint64_t timestamp_ = 0;
|
||||
uint32_t ssrc_ = 0;
|
||||
std::vector<uint32_t> 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;
|
||||
|
||||
// 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
|
||||
Reference in New Issue
Block a user