From bfe220b4fd92e935e783fc67f701c3fcad33662f Mon Sep 17 00:00:00 2001 From: Heikki Tampio Date: Tue, 22 Aug 2023 14:01:21 +0300 Subject: [PATCH] v3c: Change RTP_FORMAT_V3C into RTP_FORMAT_ATLAS --- examples/v3c_receiver.cc | 190 +---------------------------------- examples/v3c_sender.cc | 8 +- include/uvgrtp/util.hh | 2 +- include/uvgrtp/v3c_parser.hh | 6 ++ src/formats/h26x.cc | 6 +- src/frame_queue.cc | 2 +- src/media_stream.cc | 2 +- src/rtp.cc | 2 +- src/v3c_parser.cc | 182 +++++++++++++++++++++++++++++++++ 9 files changed, 200 insertions(+), 200 deletions(-) diff --git a/examples/v3c_receiver.cc b/examples/v3c_receiver.cc index fc2b599..561179d 100644 --- a/examples/v3c_receiver.cc +++ b/examples/v3c_receiver.cc @@ -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) { diff --git a/examples/v3c_sender.cc b/examples/v3c_sender.cc index 9526258..2518e6d 100644 --- a/examples/v3c_sender.cc +++ b/examples/v3c_sender.cc @@ -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; diff --git a/include/uvgrtp/util.hh b/include/uvgrtp/util.hh index 04cf5e3..c0efcaf 100644 --- a/include/uvgrtp/util.hh +++ b/include/uvgrtp/util.hh @@ -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; diff --git a/include/uvgrtp/v3c_parser.hh b/include/uvgrtp/v3c_parser.hh index e8acbc8..bd34fb2 100644 --- a/include/uvgrtp/v3c_parser.hh +++ b/include/uvgrtp/v3c_parser.hh @@ -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); diff --git a/src/formats/h26x.cc b/src/formats/h26x.cc index 2899864..4afb60f 100644 --- a/src/formats/h26x.cc +++ b/src/formats/h26x.cc @@ -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, diff --git a/src/frame_queue.cc b/src/frame_queue.cc index eaa86c4..d307324 100644 --- a/src/frame_queue.cc +++ b/src/frame_queue.cc @@ -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; diff --git a/src/media_stream.cc b/src/media_stream.cc index 761bc90..1a04b1d 100644 --- a/src/media_stream.cc +++ b/src/media_stream.cc @@ -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( diff --git a/src/rtp.cc b/src/rtp.cc index cb21190..c48ee7f 100644 --- a/src/rtp.cc +++ b/src/rtp.cc @@ -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 diff --git a/src/v3c_parser.cc b/src/v3c_parser.cc index 5ff224a..19099db 100644 --- a/src/v3c_parser.cc +++ b/src/v3c_parser.cc @@ -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; } \ No newline at end of file