v3c: Change RTP_FORMAT_V3C into RTP_FORMAT_ATLAS
This commit is contained in:
parent
11fa5d122c
commit
bfe220b4fd
|
@ -38,10 +38,7 @@ void avd_receive_hook(void* arg, uvgrtp::frame::rtp_frame* frame);
|
|||
void pvd_receive_hook(void* arg, uvgrtp::frame::rtp_frame* frame);
|
||||
void cad_receive_hook(void* arg, uvgrtp::frame::rtp_frame* frame);
|
||||
|
||||
bool is_gop_ready(uint64_t index, v3c_file_map &mmap);
|
||||
void copy_rtp_payload(uint64_t max_size, v3c_unit_info& unit, uvgrtp::frame::rtp_frame* frame);
|
||||
void create_v3c_unit(v3c_unit_info& current_unit, char* buf, uint64_t& ptr, uint64_t v3c_precision, uint32_t nal_precision);
|
||||
uint64_t reconstruct_v3c_gop(bool hdr_byte, char* buf, uint64_t &ptr, v3c_file_map &mmap, uint64_t index);
|
||||
uint64_t vps_count;
|
||||
|
||||
constexpr int VPS_NALS = 1;
|
||||
|
@ -68,12 +65,12 @@ int main(void)
|
|||
|
||||
// Create the uvgRTP media streams with the correct RTP format
|
||||
uvgrtp::media_stream* vps = sess->create_stream(8891, 8890, RTP_FORMAT_GENERIC, flags);
|
||||
uvgrtp::media_stream* ad = sess->create_stream(8893, 8892, RTP_FORMAT_V3C, flags);
|
||||
uvgrtp::media_stream* ad = sess->create_stream(8893, 8892, RTP_FORMAT_ATLAS, flags);
|
||||
uvgrtp::media_stream* ovd = sess->create_stream(8895, 8894, RTP_FORMAT_H265, flags);
|
||||
uvgrtp::media_stream* gvd = sess->create_stream(8897, 8896, RTP_FORMAT_H265, flags);
|
||||
uvgrtp::media_stream* avd = sess->create_stream(8899, 8898, RTP_FORMAT_H265, flags);
|
||||
uvgrtp::media_stream* pvd = sess->create_stream(9001, 9000, RTP_FORMAT_H265, flags);
|
||||
uvgrtp::media_stream* cad = sess->create_stream(9003, 9002, RTP_FORMAT_V3C, flags);
|
||||
uvgrtp::media_stream* cad = sess->create_stream(9003, 9002, RTP_FORMAT_ATLAS, flags);
|
||||
avd->configure_ctx(RCC_RING_BUFFER_SIZE, 40*1000*1000);
|
||||
|
||||
char* out_buf = new char[len];
|
||||
|
@ -152,189 +149,6 @@ int main(void)
|
|||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
uint64_t reconstruct_v3c_gop(bool hdr_byte, char* buf, uint64_t &ptr, v3c_file_map& mmap, uint64_t index)
|
||||
{
|
||||
/* Calculate GoP size and intiialize the output buffer
|
||||
*
|
||||
+ 1 byte of Sample Stream Precision
|
||||
+----------------------------------------------------------------+
|
||||
+ 4 bytes of V3C Unit size
|
||||
+ x1 bytes of whole V3C VPS unit (incl. header)
|
||||
+----------------------------------------------------------------+
|
||||
Atlas V3C unit
|
||||
+ 4 bytes for V3C Unit size
|
||||
+ 4 bytes of V3C header
|
||||
+ 1 byte of NAL Unit Size Precision (x1)
|
||||
+ NALs count (x1 bytes of NAL Unit Size
|
||||
+ x2 bytes of NAL unit payload)
|
||||
+----------------------------------------------------------------+
|
||||
Video V3C unit
|
||||
+ 4 bytes for V3C Unit size
|
||||
+ 4 bytes of V3C header
|
||||
+ NALs count (4 bytes of NAL Unit Size
|
||||
+ x2 bytes of NAL unit payload)
|
||||
+----------------------------------------------------------------+
|
||||
.
|
||||
.
|
||||
.
|
||||
+----------------------------------------------------------------+
|
||||
Video V3C unit
|
||||
+ 4 bytes for V3C Unit size
|
||||
+ 4 bytes of V3C header
|
||||
+ NALs count (4 bytes of NAL Unit Size
|
||||
+ x2 bytes of NAL unit payload)
|
||||
+----------------------------------------------------------------+ */
|
||||
uint8_t ATLAS_NAL_SIZE_PRECISION = 2;
|
||||
uint8_t VIDEO_NAL_SIZE_PRECISION = 4;
|
||||
uint64_t gop_size = 0;
|
||||
if (hdr_byte) {
|
||||
gop_size++; // Sample Stream Precision
|
||||
}
|
||||
uint64_t vps_size = mmap.vps_units.at(index).nal_infos.at(0).size; // incl. header
|
||||
uint64_t ad_size = 4+4+1 + mmap.ad_units.at(index).ptr + mmap.ad_units.at(index).nal_infos.size() * ATLAS_NAL_SIZE_PRECISION;
|
||||
uint64_t ovd_size = 8 + mmap.ovd_units.at(index).ptr + mmap.ovd_units.at(index).nal_infos.size() * VIDEO_NAL_SIZE_PRECISION;
|
||||
uint64_t gvd_size = 8 + mmap.gvd_units.at(index).ptr + mmap.gvd_units.at(index).nal_infos.size() * VIDEO_NAL_SIZE_PRECISION;
|
||||
uint64_t avd_size = 8 + mmap.avd_units.at(index).ptr + mmap.avd_units.at(index).nal_infos.size() * VIDEO_NAL_SIZE_PRECISION;
|
||||
gop_size += vps_size + ad_size + ovd_size + gvd_size + avd_size;
|
||||
std::cout << "Initializing GoP buffer of " << gop_size << " bytes" << std::endl;
|
||||
//buf = new char[gop_size];
|
||||
std::cout << "start ptr is " << ptr << std::endl;
|
||||
|
||||
// V3C Sample stream header
|
||||
if (hdr_byte) {
|
||||
std::cout << "Adding Sample Stream header byte" << std::endl;
|
||||
uint8_t first_byte = 64;
|
||||
buf[ptr] = first_byte;
|
||||
ptr++;
|
||||
}
|
||||
|
||||
uint8_t v3c_unit_size_precision = 3;
|
||||
|
||||
uint8_t* v3c_size_arr = new uint8_t[v3c_unit_size_precision];
|
||||
|
||||
v3c_unit_info current_unit = mmap.vps_units.at(index); // Now processing VPS unit
|
||||
uint32_t v3c_size_int = (uint32_t)current_unit.nal_infos.at(0).size;
|
||||
|
||||
// Write the V3C VPS unit size to the output buffer
|
||||
convert_size_big_endian(v3c_size_int, v3c_size_arr, v3c_unit_size_precision);
|
||||
memcpy(&buf[ptr], v3c_size_arr, v3c_unit_size_precision);
|
||||
ptr += v3c_unit_size_precision;
|
||||
|
||||
// Write the V3C VPS unit payload to the output buffer
|
||||
memcpy(&buf[ptr], current_unit.buf, v3c_size_int);
|
||||
ptr += v3c_size_int;
|
||||
|
||||
// Write out V3C AD unit
|
||||
current_unit = mmap.ad_units.at(index);
|
||||
create_v3c_unit(current_unit, buf, ptr, v3c_unit_size_precision, ATLAS_NAL_SIZE_PRECISION);
|
||||
|
||||
// Write out V3C OVD unit
|
||||
current_unit = mmap.ovd_units.at(index);
|
||||
create_v3c_unit(current_unit, buf, ptr, v3c_unit_size_precision, VIDEO_NAL_SIZE_PRECISION);
|
||||
|
||||
// Write out V3C GVD unit
|
||||
current_unit = mmap.gvd_units.at(index);
|
||||
create_v3c_unit(current_unit, buf, ptr, v3c_unit_size_precision, VIDEO_NAL_SIZE_PRECISION);
|
||||
|
||||
// Write out V3C AVD unit
|
||||
current_unit = mmap.avd_units.at(index);
|
||||
create_v3c_unit(current_unit, buf, ptr, v3c_unit_size_precision, VIDEO_NAL_SIZE_PRECISION);
|
||||
std::cout << "end ptr is " << ptr << std::endl;
|
||||
|
||||
return gop_size;
|
||||
}
|
||||
|
||||
void create_v3c_unit(v3c_unit_info ¤t_unit, char* buf, uint64_t &ptr, uint64_t v3c_precision, uint32_t nal_precision)
|
||||
{
|
||||
uint8_t v3c_type = current_unit.header.vuh_unit_type;
|
||||
|
||||
// V3C unit size
|
||||
uint8_t* v3c_size_arr = new uint8_t[v3c_precision];
|
||||
uint32_t v3c_size_int = 4 + current_unit.ptr + (uint32_t)current_unit.nal_infos.size() * nal_precision;
|
||||
if (v3c_type == V3C_AD ||v3c_type == V3C_CAD) {
|
||||
v3c_size_int++; // NAL size precision for Atlas V3C units
|
||||
}
|
||||
convert_size_big_endian(v3c_size_int, v3c_size_arr, v3c_precision);
|
||||
memcpy(&buf[ptr], v3c_size_arr, v3c_precision);
|
||||
ptr += v3c_precision;
|
||||
|
||||
// Next up create the V3C unit header
|
||||
uint8_t v3c_header[4] = {0, 0, 0, 0};
|
||||
|
||||
// All V3C unit types have parameter_set_id in header
|
||||
uint8_t param_set_id = current_unit.header.ad.vuh_v3c_parameter_set_id;
|
||||
std::cout << "VUH typ: " << (uint32_t)v3c_type << " param set id " << (uint32_t)param_set_id << std::endl;
|
||||
v3c_header[0] = v3c_type << 3 | ((param_set_id & 0b1110) >> 1);
|
||||
v3c_header[1] = ((param_set_id & 0b1) << 7);
|
||||
|
||||
// Only CAD does NOT have atlas_id
|
||||
if (v3c_type != V3C_CAD) {
|
||||
uint8_t atlas_id = current_unit.header.ad.vuh_atlas_id;
|
||||
v3c_header[1] = v3c_header[1] | ((atlas_id & 0b111111) << 1);
|
||||
}
|
||||
// GVD has map_index and aux_video_flag, then zeroes
|
||||
if (v3c_type == V3C_GVD) {
|
||||
uint8_t map_index = current_unit.header.gvd.vuh_map_index;
|
||||
bool auxiliary_video_flag = current_unit.header.gvd.vuh_auxiliary_video_flag;
|
||||
v3c_header[1] = v3c_header[1] | ((map_index & 0b1000) >> 3);
|
||||
v3c_header[2] = ((map_index & 0b111) << 5) | (auxiliary_video_flag << 4);
|
||||
}
|
||||
if (v3c_type == V3C_AVD) {
|
||||
uint8_t vuh_attribute_index = current_unit.header.avd.vuh_attribute_index;
|
||||
uint8_t vuh_attribute_partition_index = current_unit.header.avd.vuh_attribute_partition_index;
|
||||
uint8_t vuh_map_index = current_unit.header.avd.vuh_map_index;
|
||||
bool vuh_auxiliary_video_flag = current_unit.header.avd.vuh_auxiliary_video_flag;
|
||||
|
||||
v3c_header[1] = v3c_header[1] | ((vuh_attribute_index & 0b1000000) >> 7);
|
||||
v3c_header[2] = ((vuh_attribute_index & 0b111111) << 2) | ((vuh_attribute_partition_index & 0b11000) >> 3);
|
||||
v3c_header[3] = ((vuh_attribute_partition_index & 0b111) << 5) | (vuh_map_index << 1) | (int)vuh_auxiliary_video_flag;
|
||||
}
|
||||
|
||||
// Copy V3C header to outbut buffer
|
||||
memcpy(&buf[ptr], v3c_header, 4);
|
||||
ptr += 4;
|
||||
|
||||
// For Atlas V3C units, set one byte for NAL size precision
|
||||
if (v3c_type == V3C_AD || v3c_type == V3C_CAD) {
|
||||
uint8_t nal_size_precision_arr = uint8_t((nal_precision - 1) << 5);
|
||||
memcpy(&buf[ptr], &nal_size_precision_arr, 1);
|
||||
ptr++;
|
||||
}
|
||||
// For Video V3C units, NAL size precision is always 4 bytes
|
||||
|
||||
// Copy V3C unit NAL sizes and NAL units to output buffer
|
||||
for (auto& p : current_unit.nal_infos) {
|
||||
|
||||
// Copy size
|
||||
uint8_t* nal_size_arr = new uint8_t[nal_precision];
|
||||
convert_size_big_endian(uint32_t(p.size), nal_size_arr, nal_precision);
|
||||
memcpy(&buf[ptr], nal_size_arr, nal_precision);
|
||||
ptr += nal_precision;
|
||||
|
||||
// Copy NAL unit
|
||||
memcpy(&buf[ptr], ¤t_unit.buf[p.location], p.size);
|
||||
ptr += p.size;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool is_gop_ready(uint64_t index, v3c_file_map& mmap)
|
||||
{
|
||||
if (mmap.vps_units.size() < index)
|
||||
return false;
|
||||
if (mmap.ad_units.size() < index || !mmap.ad_units.at(index-1).ready)
|
||||
return false;
|
||||
if (mmap.ovd_units.size() < index || !mmap.ovd_units.at(index-1).ready)
|
||||
return false;
|
||||
if (mmap.gvd_units.size() < index || !mmap.gvd_units.at(index-1).ready)
|
||||
return false;
|
||||
if (mmap.avd_units.size() < index || !mmap.avd_units.at(index-1).ready)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void copy_rtp_payload(uint64_t max_size, v3c_unit_info &unit, uvgrtp::frame::rtp_frame *frame)
|
||||
{
|
||||
if (unit.nal_infos.size() <= max_size) {
|
||||
|
|
|
@ -27,7 +27,7 @@ int main(void)
|
|||
/* A V3C Sample stream is divided into 6 types of 'sub-bitstreams' + parameters.
|
||||
- The nal_map holds nal_info structs
|
||||
- nal_info struct holds the format(Atlas, H264, H265, H266), start position and size of the NAL unit
|
||||
- With this info you can send the data via different uvgRTP media streams. Usually 2 streams, one in RTP_FORMAT_V3C for
|
||||
- With this info you can send the data via different uvgRTP media streams. Usually 2 streams, one in RTP_FORMAT_ATLAS for
|
||||
Atlas NAL units and a second one for the video NAL units in the correct format
|
||||
|
||||
Note: Use RTP_NO_H26X_SCL when sending video frames, as there is no start codes in the video sub-streams */
|
||||
|
@ -52,12 +52,12 @@ int main(void)
|
|||
|
||||
// Create the uvgRTP media streams with the correct RTP format
|
||||
uvgrtp::media_stream* vps = sess->create_stream(8890, 8891, RTP_FORMAT_GENERIC, flags);
|
||||
uvgrtp::media_stream* ad = sess->create_stream(8892, 8893, RTP_FORMAT_V3C, flags);
|
||||
uvgrtp::media_stream* ad = sess->create_stream(8892, 8893, RTP_FORMAT_ATLAS, flags);
|
||||
uvgrtp::media_stream* ovd = sess->create_stream(8894, 8895, RTP_FORMAT_H265, flags);
|
||||
uvgrtp::media_stream* gvd = sess->create_stream(8896, 8897, RTP_FORMAT_H265, flags);
|
||||
uvgrtp::media_stream* avd = sess->create_stream(8898, 8899, RTP_FORMAT_H265, flags);
|
||||
uvgrtp::media_stream* pvd = sess->create_stream(9000, 9001, RTP_FORMAT_H265, flags);
|
||||
uvgrtp::media_stream* cad = sess->create_stream(9002, 9003, RTP_FORMAT_V3C, flags);
|
||||
uvgrtp::media_stream* cad = sess->create_stream(9002, 9003, RTP_FORMAT_ATLAS, flags);
|
||||
|
||||
|
||||
uint64_t send_ptr = 0;
|
||||
|
@ -153,14 +153,12 @@ void sender_func(uvgrtp::media_stream* stream, const char* cbuf, const std::vect
|
|||
double time_100m = bytes_sent / 100; // us so dont multiply *1000 * 1000;
|
||||
double time_1g = bytes_sent / (1 * 1000); // us so dont multiply *1000 * 1000;
|
||||
double time_10g = bytes_sent / (10 * 1000); // us so dont multiply *1000 * 1000;
|
||||
std::cout << "bytes sent " << bytes_sent << std::endl;
|
||||
std::string line = std::to_string(index) + ";" + std::to_string(i.size) + ";" + std::to_string(bytes_sent) + ";"
|
||||
+ std::to_string(time_100m) + ";"
|
||||
+ std::to_string(time_1g) + ";"
|
||||
+ std::to_string(time_10g) + ";" + "\n";
|
||||
|
||||
//myfile << line;
|
||||
std::cout << line << std::endl;
|
||||
}
|
||||
else {
|
||||
std::cout << "Failed to send RTP frame!" << std::endl;
|
||||
|
|
|
@ -124,7 +124,7 @@ typedef enum RTP_FORMAT {
|
|||
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_V3C = 109 ///< V3C
|
||||
RTP_FORMAT_ATLAS = 109 ///< V3C
|
||||
|
||||
} rtp_format_t;
|
||||
|
||||
|
|
|
@ -125,3 +125,9 @@ void parse_v3c_header(v3c_unit_header &hdr, char* buf, uint64_t ptr);
|
|||
|
||||
void parse_vps_ptl(profile_tier_level &ptl, char* buf, uint64_t ptr);
|
||||
|
||||
// Receiver functions
|
||||
void create_v3c_unit(v3c_unit_info& current_unit, char* buf, uint64_t& ptr, uint64_t v3c_precision, uint32_t nal_precision);
|
||||
uint64_t reconstruct_v3c_gop(bool hdr_byte, char* buf, uint64_t& ptr, v3c_file_map& mmap, uint64_t index);
|
||||
|
||||
|
||||
bool is_gop_ready(uint64_t index, v3c_file_map& mmap);
|
||||
|
|
|
@ -330,7 +330,7 @@ rtp_error_t uvgrtp::formats::h26x::push_media_frame(sockaddr_in& addr, sockaddr_
|
|||
|
||||
rtp_format_t fmt = rtp_ctx_->get_payload();
|
||||
|
||||
if ((rtp_flags & RTP_NO_H26X_SCL) || (fmt == RTP_FORMAT_V3C)) {
|
||||
if ((rtp_flags & RTP_NO_H26X_SCL) || (fmt == RTP_FORMAT_ATLAS)) {
|
||||
nal_info nal;
|
||||
nal.offset = 0;
|
||||
nal.prefix_len = 0;
|
||||
|
@ -517,7 +517,7 @@ uvgrtp::frame::rtp_frame* uvgrtp::formats::h26x::allocate_rtp_frame_with_startco
|
|||
void uvgrtp::formats::h26x::prepend_start_code(int rce_flags, uvgrtp::frame::rtp_frame** out)
|
||||
{
|
||||
rtp_format_t fmt = rtp_ctx_->get_payload();
|
||||
if (fmt == RTP_FORMAT_V3C) {
|
||||
if (fmt == RTP_FORMAT_ATLAS) {
|
||||
return;
|
||||
}
|
||||
if (!(rce_flags & RCE_NO_H26X_PREPEND_SC)) {
|
||||
|
@ -967,7 +967,7 @@ rtp_error_t uvgrtp::formats::h26x::reconstruction(uvgrtp::frame::rtp_frame** out
|
|||
|
||||
// allocating the frame with start code ready saves a copy operation for the frame
|
||||
bool start_code = !(rce_flags & RCE_NO_H26X_PREPEND_SC);
|
||||
if (rtp_ctx_->get_payload() == RTP_FORMAT_V3C) {
|
||||
if (rtp_ctx_->get_payload() == RTP_FORMAT_ATLAS) {
|
||||
start_code = false;
|
||||
}
|
||||
uvgrtp::frame::rtp_frame* complete = allocate_rtp_frame_with_startcode(start_code,
|
||||
|
|
|
@ -78,7 +78,7 @@ rtp_error_t uvgrtp::frame_queue::init_transaction()
|
|||
active_->media_headers = new uvgrtp::formats::h266_headers;
|
||||
break;
|
||||
|
||||
case RTP_FORMAT_V3C:
|
||||
case RTP_FORMAT_ATLAS:
|
||||
active_->media_headers = new uvgrtp::formats::v3c_headers;
|
||||
break;
|
||||
|
||||
|
|
|
@ -225,7 +225,7 @@ rtp_error_t uvgrtp::media_stream::create_media(rtp_format_t fmt)
|
|||
media_.reset(format_266);
|
||||
break;
|
||||
}
|
||||
case RTP_FORMAT_V3C:
|
||||
case RTP_FORMAT_ATLAS:
|
||||
{
|
||||
uvgrtp::formats::v3c* format_v3c = new uvgrtp::formats::v3c(socket_, rtp_, rce_flags_);
|
||||
reception_flow_->install_handler(
|
||||
|
|
|
@ -97,7 +97,7 @@ void uvgrtp::rtp::set_default_clock_rate(rtp_format_t fmt)
|
|||
case RTP_FORMAT_H264:
|
||||
case RTP_FORMAT_H265:
|
||||
case RTP_FORMAT_H266:
|
||||
case RTP_FORMAT_V3C:
|
||||
case RTP_FORMAT_ATLAS:
|
||||
clock_rate_ = 90000;
|
||||
break;
|
||||
case RTP_FORMAT_L8: // variable, user should set this
|
||||
|
|
|
@ -342,4 +342,186 @@ char* get_cmem(std::string filename, const size_t& len)
|
|||
}
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
void create_v3c_unit(v3c_unit_info& current_unit, char* buf, uint64_t& ptr, uint64_t v3c_precision, uint32_t nal_precision)
|
||||
{
|
||||
uint8_t v3c_type = current_unit.header.vuh_unit_type;
|
||||
|
||||
// V3C unit size
|
||||
uint8_t* v3c_size_arr = new uint8_t[v3c_precision];
|
||||
uint32_t v3c_size_int = 4 + current_unit.ptr + (uint32_t)current_unit.nal_infos.size() * nal_precision;
|
||||
if (v3c_type == V3C_AD || v3c_type == V3C_CAD) {
|
||||
v3c_size_int++; // NAL size precision for Atlas V3C units
|
||||
}
|
||||
convert_size_big_endian(v3c_size_int, v3c_size_arr, v3c_precision);
|
||||
memcpy(&buf[ptr], v3c_size_arr, v3c_precision);
|
||||
ptr += v3c_precision;
|
||||
|
||||
// Next up create the V3C unit header
|
||||
uint8_t v3c_header[4] = { 0, 0, 0, 0 };
|
||||
|
||||
// All V3C unit types have parameter_set_id in header
|
||||
uint8_t param_set_id = current_unit.header.ad.vuh_v3c_parameter_set_id;
|
||||
std::cout << "VUH typ: " << (uint32_t)v3c_type << " param set id " << (uint32_t)param_set_id << std::endl;
|
||||
v3c_header[0] = v3c_type << 3 | ((param_set_id & 0b1110) >> 1);
|
||||
v3c_header[1] = ((param_set_id & 0b1) << 7);
|
||||
|
||||
// Only CAD does NOT have atlas_id
|
||||
if (v3c_type != V3C_CAD) {
|
||||
uint8_t atlas_id = current_unit.header.ad.vuh_atlas_id;
|
||||
v3c_header[1] = v3c_header[1] | ((atlas_id & 0b111111) << 1);
|
||||
}
|
||||
// GVD has map_index and aux_video_flag, then zeroes
|
||||
if (v3c_type == V3C_GVD) {
|
||||
uint8_t map_index = current_unit.header.gvd.vuh_map_index;
|
||||
bool auxiliary_video_flag = current_unit.header.gvd.vuh_auxiliary_video_flag;
|
||||
v3c_header[1] = v3c_header[1] | ((map_index & 0b1000) >> 3);
|
||||
v3c_header[2] = ((map_index & 0b111) << 5) | (auxiliary_video_flag << 4);
|
||||
}
|
||||
if (v3c_type == V3C_AVD) {
|
||||
uint8_t vuh_attribute_index = current_unit.header.avd.vuh_attribute_index;
|
||||
uint8_t vuh_attribute_partition_index = current_unit.header.avd.vuh_attribute_partition_index;
|
||||
uint8_t vuh_map_index = current_unit.header.avd.vuh_map_index;
|
||||
bool vuh_auxiliary_video_flag = current_unit.header.avd.vuh_auxiliary_video_flag;
|
||||
|
||||
v3c_header[1] = v3c_header[1] | ((vuh_attribute_index & 0b1000000) >> 7);
|
||||
v3c_header[2] = ((vuh_attribute_index & 0b111111) << 2) | ((vuh_attribute_partition_index & 0b11000) >> 3);
|
||||
v3c_header[3] = ((vuh_attribute_partition_index & 0b111) << 5) | (vuh_map_index << 1) | (int)vuh_auxiliary_video_flag;
|
||||
}
|
||||
|
||||
// Copy V3C header to outbut buffer
|
||||
memcpy(&buf[ptr], v3c_header, 4);
|
||||
ptr += 4;
|
||||
|
||||
// For Atlas V3C units, set one byte for NAL size precision
|
||||
if (v3c_type == V3C_AD || v3c_type == V3C_CAD) {
|
||||
uint8_t nal_size_precision_arr = uint8_t((nal_precision - 1) << 5);
|
||||
memcpy(&buf[ptr], &nal_size_precision_arr, 1);
|
||||
ptr++;
|
||||
}
|
||||
// For Video V3C units, NAL size precision is always 4 bytes
|
||||
|
||||
// Copy V3C unit NAL sizes and NAL units to output buffer
|
||||
for (auto& p : current_unit.nal_infos) {
|
||||
|
||||
// Copy size
|
||||
uint8_t* nal_size_arr = new uint8_t[nal_precision];
|
||||
convert_size_big_endian(uint32_t(p.size), nal_size_arr, nal_precision);
|
||||
memcpy(&buf[ptr], nal_size_arr, nal_precision);
|
||||
ptr += nal_precision;
|
||||
|
||||
// Copy NAL unit
|
||||
memcpy(&buf[ptr], ¤t_unit.buf[p.location], p.size);
|
||||
ptr += p.size;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
uint64_t reconstruct_v3c_gop(bool hdr_byte, char* buf, uint64_t& ptr, v3c_file_map& mmap, uint64_t index)
|
||||
{
|
||||
/* Calculate GoP size and intiialize the output buffer
|
||||
*
|
||||
+ 1 byte of Sample Stream Precision
|
||||
+----------------------------------------------------------------+
|
||||
+ 4 bytes of V3C Unit size
|
||||
+ x1 bytes of whole V3C VPS unit (incl. header)
|
||||
+----------------------------------------------------------------+
|
||||
Atlas V3C unit
|
||||
+ 4 bytes for V3C Unit size
|
||||
+ 4 bytes of V3C header
|
||||
+ 1 byte of NAL Unit Size Precision (x1)
|
||||
+ NALs count (x1 bytes of NAL Unit Size
|
||||
+ x2 bytes of NAL unit payload)
|
||||
+----------------------------------------------------------------+
|
||||
Video V3C unit
|
||||
+ 4 bytes for V3C Unit size
|
||||
+ 4 bytes of V3C header
|
||||
+ NALs count (4 bytes of NAL Unit Size
|
||||
+ x2 bytes of NAL unit payload)
|
||||
+----------------------------------------------------------------+
|
||||
.
|
||||
.
|
||||
.
|
||||
+----------------------------------------------------------------+
|
||||
Video V3C unit
|
||||
+ 4 bytes for V3C Unit size
|
||||
+ 4 bytes of V3C header
|
||||
+ NALs count (4 bytes of NAL Unit Size
|
||||
+ x2 bytes of NAL unit payload)
|
||||
+----------------------------------------------------------------+ */
|
||||
uint8_t ATLAS_NAL_SIZE_PRECISION = 2;
|
||||
uint8_t VIDEO_NAL_SIZE_PRECISION = 4;
|
||||
uint64_t gop_size = 0;
|
||||
if (hdr_byte) {
|
||||
gop_size++; // Sample Stream Precision
|
||||
}
|
||||
uint64_t vps_size = mmap.vps_units.at(index).nal_infos.at(0).size; // incl. header
|
||||
uint64_t ad_size = 4 + 4 + 1 + mmap.ad_units.at(index).ptr + mmap.ad_units.at(index).nal_infos.size() * ATLAS_NAL_SIZE_PRECISION;
|
||||
uint64_t ovd_size = 8 + mmap.ovd_units.at(index).ptr + mmap.ovd_units.at(index).nal_infos.size() * VIDEO_NAL_SIZE_PRECISION;
|
||||
uint64_t gvd_size = 8 + mmap.gvd_units.at(index).ptr + mmap.gvd_units.at(index).nal_infos.size() * VIDEO_NAL_SIZE_PRECISION;
|
||||
uint64_t avd_size = 8 + mmap.avd_units.at(index).ptr + mmap.avd_units.at(index).nal_infos.size() * VIDEO_NAL_SIZE_PRECISION;
|
||||
gop_size += vps_size + ad_size + ovd_size + gvd_size + avd_size;
|
||||
std::cout << "Initializing GoP buffer of " << gop_size << " bytes" << std::endl;
|
||||
//buf = new char[gop_size];
|
||||
std::cout << "start ptr is " << ptr << std::endl;
|
||||
|
||||
// V3C Sample stream header
|
||||
if (hdr_byte) {
|
||||
std::cout << "Adding Sample Stream header byte" << std::endl;
|
||||
uint8_t first_byte = 64;
|
||||
buf[ptr] = first_byte;
|
||||
ptr++;
|
||||
}
|
||||
|
||||
uint8_t v3c_unit_size_precision = 3;
|
||||
|
||||
uint8_t* v3c_size_arr = new uint8_t[v3c_unit_size_precision];
|
||||
|
||||
v3c_unit_info current_unit = mmap.vps_units.at(index); // Now processing VPS unit
|
||||
uint32_t v3c_size_int = (uint32_t)current_unit.nal_infos.at(0).size;
|
||||
|
||||
// Write the V3C VPS unit size to the output buffer
|
||||
convert_size_big_endian(v3c_size_int, v3c_size_arr, v3c_unit_size_precision);
|
||||
memcpy(&buf[ptr], v3c_size_arr, v3c_unit_size_precision);
|
||||
ptr += v3c_unit_size_precision;
|
||||
|
||||
// Write the V3C VPS unit payload to the output buffer
|
||||
memcpy(&buf[ptr], current_unit.buf, v3c_size_int);
|
||||
ptr += v3c_size_int;
|
||||
|
||||
// Write out V3C AD unit
|
||||
current_unit = mmap.ad_units.at(index);
|
||||
create_v3c_unit(current_unit, buf, ptr, v3c_unit_size_precision, ATLAS_NAL_SIZE_PRECISION);
|
||||
|
||||
// Write out V3C OVD unit
|
||||
current_unit = mmap.ovd_units.at(index);
|
||||
create_v3c_unit(current_unit, buf, ptr, v3c_unit_size_precision, VIDEO_NAL_SIZE_PRECISION);
|
||||
|
||||
// Write out V3C GVD unit
|
||||
current_unit = mmap.gvd_units.at(index);
|
||||
create_v3c_unit(current_unit, buf, ptr, v3c_unit_size_precision, VIDEO_NAL_SIZE_PRECISION);
|
||||
|
||||
// Write out V3C AVD unit
|
||||
current_unit = mmap.avd_units.at(index);
|
||||
create_v3c_unit(current_unit, buf, ptr, v3c_unit_size_precision, VIDEO_NAL_SIZE_PRECISION);
|
||||
std::cout << "end ptr is " << ptr << std::endl;
|
||||
|
||||
return gop_size;
|
||||
}
|
||||
|
||||
bool is_gop_ready(uint64_t index, v3c_file_map& mmap)
|
||||
{
|
||||
if (mmap.vps_units.size() < index)
|
||||
return false;
|
||||
if (mmap.ad_units.size() < index || !mmap.ad_units.at(index - 1).ready)
|
||||
return false;
|
||||
if (mmap.ovd_units.size() < index || !mmap.ovd_units.at(index - 1).ready)
|
||||
return false;
|
||||
if (mmap.gvd_units.size() < index || !mmap.gvd_units.at(index - 1).ready)
|
||||
return false;
|
||||
if (mmap.avd_units.size() < index || !mmap.avd_units.at(index - 1).ready)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
Loading…
Reference in New Issue