v3c: Add basic support for V3C RTP format
This commit is contained in:
parent
28a270b839
commit
017f23099c
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue