From f417e828ae61a699d0276ded50085978be7b66de Mon Sep 17 00:00:00 2001 From: Heikki Tampio Date: Wed, 23 Aug 2023 13:45:58 +0300 Subject: [PATCH] v3c: Add documentation to the examples --- examples/v3c/v3c_util.cc | 13 +++++++------ examples/v3c/v3c_util.hh | 9 ++++++--- examples/v3c_receiver.cc | 23 +++++++++++++++------- examples/v3c_sender.cc | 42 ++++++++++++++++++++++++---------------- test/test_common.hh | 2 +- 5 files changed, 55 insertions(+), 34 deletions(-) diff --git a/examples/v3c/v3c_util.cc b/examples/v3c/v3c_util.cc index 97f0ac7..4774d4f 100644 --- a/examples/v3c/v3c_util.cc +++ b/examples/v3c/v3c_util.cc @@ -451,7 +451,8 @@ uint64_t reconstruct_v3c_gop(bool hdr_byte, char* &buf, uint64_t& ptr, v3c_file_ 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]; + // Commented out because we want to write the whole file into the buffer, not GoP by GoP + //buf = new char[gop_size]; // V3C Sample stream header if (hdr_byte) { @@ -495,15 +496,15 @@ uint64_t reconstruct_v3c_gop(bool hdr_byte, char* &buf, uint64_t& ptr, v3c_file_ bool is_gop_ready(uint64_t index, v3c_file_map& mmap) { - if (mmap.vps_units.size() < index) + if (mmap.vps_units.size() < index+1) return false; - if (mmap.ad_units.size() < index || !mmap.ad_units.at(index - 1).ready) + if (mmap.ad_units.size() < index+1 || !mmap.ad_units.at(index).ready) return false; - if (mmap.ovd_units.size() < index || !mmap.ovd_units.at(index - 1).ready) + if (mmap.ovd_units.size() < index+1 || !mmap.ovd_units.at(index).ready) return false; - if (mmap.gvd_units.size() < index || !mmap.gvd_units.at(index - 1).ready) + if (mmap.gvd_units.size() < index+1 || !mmap.gvd_units.at(index).ready) return false; - if (mmap.avd_units.size() < index || !mmap.avd_units.at(index - 1).ready) + if (mmap.avd_units.size() < index+1 || !mmap.avd_units.at(index).ready) return false; return true; diff --git a/examples/v3c/v3c_util.hh b/examples/v3c/v3c_util.hh index dc5b0ba..86559fe 100644 --- a/examples/v3c/v3c_util.hh +++ b/examples/v3c/v3c_util.hh @@ -80,12 +80,15 @@ struct nal_info { uint64_t size = 0; // Sie of the NAL unit }; +/* A v3c_unit_info contains all the required information of a V3C unit + - 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. */ struct v3c_unit_info { v3c_unit_header header; std::vector nal_infos = {}; - char* buf; - uint64_t ptr = 0; - bool ready = false; + char* buf; // (used on the receiving end) + uint64_t ptr = 0; // (used on the receiving end) + bool ready = false; // (used on the receiving end) }; struct v3c_file_map { diff --git a/examples/v3c_receiver.cc b/examples/v3c_receiver.cc index 751f941..8d3e52d 100644 --- a/examples/v3c_receiver.cc +++ b/examples/v3c_receiver.cc @@ -18,14 +18,21 @@ void avd_receive_hook(void* arg, uvgrtp::frame::rtp_frame* frame); uint64_t vps_count; -constexpr int VPS_NALS = 1; +/* These values specify the amount of NAL units inside each type of V3C unit. These need to be known to be able to reconstruct the + * file after receiving. These might be different for you depending on your test file. The sending example has prints that show + * how many NAL units each V3C unit contain. Change these accordingly. */ +constexpr int VPS_NALS = 2; constexpr int AD_NALS = 35; constexpr int OVD_NALS = 35; constexpr int GVD_NALS = 131; constexpr int AVD_NALS = 131; + +/* How many Groups of Pictures we are expecting to receive */ constexpr int EXPECTED_GOPS = 1; -std::string PATH = "C:\\Users\\ngheta\\Documents\\v3c_test_seq_2.vpcc"; +/* Path to the V3C file that we are receiving.This is included so that you can check that the reconstructed file is equal to the + * original one */ +std::string PATH = ""; int main(void) { @@ -44,7 +51,8 @@ int main(void) // Create the uvgRTP media streams with the correct RTP format v3c_streams streams = init_v3c_streams(sess, 8890, 8892, flags, true); - //avd->configure_ctx(RCC_RING_BUFFER_SIZE, 40*1000*1000); + + // Initialize memory map v3c_file_map mmap = init_mmap(); streams.vps->install_receive_hook(&mmap.vps_units, vps_receive_hook); @@ -52,18 +60,19 @@ int main(void) streams.ovd->install_receive_hook(&mmap.ovd_units, ovd_receive_hook); streams.gvd->install_receive_hook(&mmap.gvd_units, gvd_receive_hook); streams.avd->install_receive_hook(&mmap.avd_units, avd_receive_hook); - + streams.avd->configure_ctx(RCC_RING_BUFFER_SIZE, 40 * 1000 * 1000); std::cout << "Waiting incoming packets for " << RECEIVE_TIME_S.count() << " s" << std::endl; - uint64_t ngops = 1; + uint64_t ngops = 0; uint64_t bytes = 0; uint64_t ptr = 0; bool hdb = true; - char* out_buf = nullptr; + char* out_buf = new char[len]; // Initialize to nullptr if you want to output the file GoP by GoP while (ngops <= EXPECTED_GOPS) { if (is_gop_ready(ngops, mmap)) { - bytes += reconstruct_v3c_gop(hdb, out_buf, ptr, mmap, ngops - 1); + //ptr = 0; Don't reset the ptr because we are writing the whole file into the buffer + bytes += reconstruct_v3c_gop(hdb, out_buf, ptr, mmap, ngops); std::cout << "Full GoP received, num: " << ngops << std::endl; ngops++; hdb = false; // Only add the V3C Sample Stream header byte to only the first GoP diff --git a/examples/v3c_sender.cc b/examples/v3c_sender.cc index a796306..0d2cad8 100644 --- a/examples/v3c_sender.cc +++ b/examples/v3c_sender.cc @@ -10,30 +10,38 @@ constexpr char REMOTE_ADDRESS[] = "127.0.0.1"; -std::string PATH = "C:\\Users\\ngheta\\Documents\\v3c_test_seq_2.vpcc"; - +// Path to the V3C file that you want to send +std::string PATH = ""; void sender_func(uvgrtp::media_stream* stream, const char* cbuf, const std::vector &units, rtp_flags_t flags, int fmt); std::atomic bytes_sent; int main(void) { + /* This example demonstrates sending V3C Sample Stream files via uvgRTP. The V3C Sample Stream contains a V3C Sample Stream + * header byte and multiple V3C Units with their sizes specified before each unit. A V3C Unit then contains a V3C header + * and Atlas or Video NAL units, depending on the V3C unit type. + * + * The process of sending a V3C Cample Stream file via uvgRTP contains the following steps: + * Parse file and extract locations and sizes of NAL units -> Send NAL units in separate uvgRTP media streams + * -> Receive NAL units -> Reconstruct V3C Sample Stream + * + * In this example there are in total 5 media streams, one for each component: + * 1. Parameter set stream + * 2. Atlas stream + * 3. Occupancy Video stream + * 4. Geometry Video stream + * 5. Attribute Video Stream + * + * There is also the possibility to have two more streams: Packed Video and Common Atlas Data. These are not included in + * this example as our test files don't have them. If you need these, it should be quite easy to implement them + * + * A few notes for users: This example expects there to be no packet loss. If some NAL units are lost in transmission, + * the reconstruction will not work. + * Please also read the documentation on v3c_receiver.cc before testing this example. */ + std::cout << "Parsing V3C file" << std::endl; - /* A V3C Sample stream is divided into 4 types of 'sub-bitstreams' + parameters. - - In v3c_file_map there are vectors of - - V3C unit infos - - v3c_unit_infos - - header - - nal_infos - - buf - - ptr - - ready - - - The nal_infos 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. - - Note: Use RTP_NO_H26X_SCL when sending video frames, as there is no start codes in the video sub-streams */ + /* Note: Use RTP_NO_H26X_SCL when sending video frames, as there is no start codes in the video sub-streams */ bytes_sent = 0; v3c_file_map mmap; diff --git a/test/test_common.hh b/test/test_common.hh index 54e1d7a..a1a6b40 100644 --- a/test/test_common.hh +++ b/test/test_common.hh @@ -207,7 +207,7 @@ inline void test_packet_size(std::unique_ptr test_packet, int packets Test_receiver* tester = new Test_receiver(packets); int interval_ms = 1000/framerate; - if (format == RTP_FORMAT_V3C) { + if (format == RTP_FORMAT_ATLAS) { add_hook(tester, receiver, v3c_rtp_hook); } else {