v3c: Add basic support for V3C RTP format

This commit is contained in:
Heikki Tampio 2023-08-07 10:57:34 +03:00
parent 28a270b839
commit 017f23099c
5 changed files with 210 additions and 1 deletions

View File

@ -82,6 +82,7 @@ target_sources(${PROJECT_NAME} PRIVATE
src/formats/h264.cc
src/formats/h265.cc
src/formats/h266.cc
src/formats/v3c.cc
src/zrtp/zrtp_receiver.cc
src/zrtp/hello.cc
@ -130,6 +131,7 @@ target_sources(${PROJECT_NAME} PRIVATE
src/formats/h265.hh
src/formats/h266.hh
src/formats/media.hh
src/formats/v3c.hh
src/srtp/base.hh
src/srtp/srtcp.hh

View File

@ -123,7 +123,8 @@ typedef enum RTP_FORMAT {
// H263-1998 is unsupported in uvgRTP
RTP_FORMAT_H264 = 106, ///< H.264/AVC, see RFC 6184
RTP_FORMAT_H265 = 107, ///< H.265/HEVC, see RFC 7798
RTP_FORMAT_H266 = 108 ///< H.266/VVC
RTP_FORMAT_H266 = 108, ///< H.266/VVC
RTP_FORMAT_V3C = 109 ///< V3C
} rtp_format_t;

118
src/formats/v3c.cc Normal file
View File

@ -0,0 +1,118 @@
#include "v3c.hh"
#include "uvgrtp/frame.hh"
#include "../rtp.hh"
#include "../frame_queue.hh"
#include "debug.hh"
#include <cstdint>
#include <cstring>
#include <iostream>
#include <unordered_map>
#include <unordered_set>
#include <map>
#include <queue>
#ifndef _WIN32
#include <sys/socket.h>
#endif
uvgrtp::formats::v3c::v3c(std::shared_ptr<uvgrtp::socket> socket, std::shared_ptr<uvgrtp::rtp> rtp, int rce_flags) :
h26x(socket, rtp, rce_flags)
{}
uvgrtp::formats::v3c::~v3c()
{
}
uint8_t uvgrtp::formats::v3c::get_payload_header_size() const
{
return HEADER_SIZE_V3C_PAYLOAD;
}
uint8_t uvgrtp::formats::v3c::get_nal_header_size() const
{
return HEADER_SIZE_V3C_NAL;
}
uint8_t uvgrtp::formats::v3c::get_fu_header_size() const
{
return HEADER_SIZE_V3C_FU;
}
uint8_t uvgrtp::formats::v3c::get_start_code_range() const
{
return 4;
}
uvgrtp::formats::NAL_TYPE uvgrtp::formats::v3c::get_nal_type(uvgrtp::frame::rtp_frame* frame) const
{
uint8_t nal_type = frame->payload[2] & 0x3f;
/*
if (nal_type == H266_IDR_W_RADL)
return uvgrtp::formats::NAL_TYPE::NT_INTRA;
else if (nal_type == H266_TRAIL_NUT)
return uvgrtp::formats::NAL_TYPE::NT_INTER;
*/
return uvgrtp::formats::NAL_TYPE::NT_OTHER;
}
uint8_t uvgrtp::formats::v3c::get_nal_type(uint8_t* data) const
{
//return (data[1] >> 3) & 0x1f;
return data[0] & 0x10F447;
}
uvgrtp::formats::FRAG_TYPE uvgrtp::formats::v3c::get_fragment_type(uvgrtp::frame::rtp_frame* frame) const
{
// Same bits as in VVC FU headers
bool first_frag = frame->payload[2] & 0x80;
bool last_frag = frame->payload[2] & 0x40;
if ((frame->payload[1] >> 3) != uvgrtp::formats::V3C_PKT_FRAG)
return uvgrtp::formats::FRAG_TYPE::FT_NOT_FRAG; // Single NAL unit
if (first_frag && last_frag)
return uvgrtp::formats::FRAG_TYPE::FT_INVALID;
if (first_frag)
return uvgrtp::formats::FRAG_TYPE::FT_START;
if (last_frag)
return uvgrtp::formats::FRAG_TYPE::FT_END;
return uvgrtp::formats::FRAG_TYPE::FT_MIDDLE;
}
void uvgrtp::formats::v3c::get_nal_header_from_fu_headers(size_t fptr, uint8_t* frame_payload, uint8_t* complete_payload)
{
uint8_t payload_header[2] = {
(uint8_t)((frame_payload[0])),
(uint8_t)((frame_payload[1] & 0x7) | ((frame_payload[2] & 0x3f) << 3))
};
std::memcpy(&complete_payload[fptr], payload_header, get_payload_header_size());
}
rtp_error_t uvgrtp::formats::v3c::fu_division(uint8_t* data, size_t data_len, size_t payload_size)
{
auto headers = (uvgrtp::formats::v3c_headers*)fqueue_->get_media_headers();
headers->payload_header[0] = data[0];
headers->payload_header[1] = (V3C_PKT_FRAG << 3) | (data[1] & 0x7);
initialize_fu_headers(get_nal_type(data), headers->fu_headers);
uvgrtp::buf_vec* buffers = fqueue_->get_buffer_vector();
buffers->push_back(std::make_pair(sizeof(headers->payload_header), headers->payload_header));
buffers->push_back(std::make_pair(sizeof(uint8_t), &headers->fu_headers[0]));
buffers->push_back(std::make_pair(payload_size, nullptr));
return divide_frame_to_fus(data, data_len, payload_size, *buffers, headers->fu_headers);
}

73
src/formats/v3c.hh Normal file
View File

@ -0,0 +1,73 @@
#pragma once
#include "uvgrtp/util.hh"
#include "uvgrtp/clock.hh"
#include "uvgrtp/frame.hh"
#include "h26x.hh"
#include "socket.hh"
#include <deque>
#include <memory>
namespace uvgrtp {
class rtp;
namespace formats {
constexpr uint8_t HEADER_SIZE_V3C_PAYLOAD = 2;
constexpr uint8_t HEADER_SIZE_V3C_NAL = 2;
constexpr uint8_t HEADER_SIZE_V3C_FU = 1;
enum V3C_NAL_TYPES {
NAL_BLA_W_LP,
NAL_RSV_IRAP_ACL_29
};
enum V3C_PKT_TYPES {
V3C_PKT_AGGR = 56,
V3C_PKT_FRAG = 58
};
struct v3c_aggregation_packet {
uint8_t payload_header[HEADER_SIZE_V3C_PAYLOAD];
uvgrtp::buf_vec nalus; /* discrete NAL units */
uvgrtp::buf_vec aggr_pkt; /* crafted aggregation packet */
};
struct v3c_headers {
uint8_t payload_header[HEADER_SIZE_V3C_PAYLOAD];
/* there are three types of Fragmentation Unit headers:
* - header for the first fragment
* - header for all middle fragments
* - header for the last fragment */
uint8_t fu_headers[3 * HEADER_SIZE_V3C_FU];
};
class v3c : public h26x {
public:
v3c(std::shared_ptr<uvgrtp::socket> socket, std::shared_ptr<uvgrtp::rtp> rtp, int rce_flags);
~v3c();
protected:
// constructs v3c RTP header with correct values
virtual rtp_error_t fu_division(uint8_t* data, size_t data_len, size_t payload_size);
virtual uint8_t get_nal_type(uint8_t* data) const;
virtual void get_nal_header_from_fu_headers(size_t fptr, uint8_t* frame_payload, uint8_t* complete_payload);
virtual uint8_t get_payload_header_size() const;
virtual uint8_t get_nal_header_size() const;
virtual uint8_t get_fu_header_size() const;
virtual uint8_t get_start_code_range() const;
virtual uvgrtp::formats::FRAG_TYPE get_fragment_type(uvgrtp::frame::rtp_frame* frame) const;
virtual uvgrtp::formats::NAL_TYPE get_nal_type(uvgrtp::frame::rtp_frame* frame) const;
};
}
}
namespace uvg_rtp = uvgrtp;

View File

@ -5,6 +5,7 @@
#include "formats/h264.hh"
#include "formats/h265.hh"
#include "formats/h266.hh"
#include "formats/v3c.hh"
#include "debug.hh"
#include "random.hh"
#include "rtp.hh"
@ -224,6 +225,20 @@ rtp_error_t uvgrtp::media_stream::create_media(rtp_format_t fmt)
media_.reset(format_266);
break;
}
case RTP_FORMAT_V3C:
{
uvgrtp::formats::v3c* format_v3c = new uvgrtp::formats::v3c(socket_, rtp_, rce_flags_);
reception_flow_->install_handler(
5, remote_ssrc_,
std::bind(&uvgrtp::formats::v3c::packet_handler, format_v3c, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3,
std::placeholders::_4, std::placeholders::_5), nullptr
);
reception_flow_->install_getter(remote_ssrc_,
std::bind(&uvgrtp::formats::v3c::frame_getter, format_v3c, std::placeholders::_1));
media_.reset(format_v3c);
break;
}
case RTP_FORMAT_OPUS:
case RTP_FORMAT_PCMU:
case RTP_FORMAT_GSM: