diff --git a/examples/v3c_receiver.cc b/examples/v3c_receiver.cc index 038493a..3d527a4 100644 --- a/examples/v3c_receiver.cc +++ b/examples/v3c_receiver.cc @@ -73,7 +73,7 @@ int main(void) std::this_thread::sleep_for(RECEIVE_TIME_S); // lets this example run for some time std::cout << "V3C Total bytes received " << vbytes_received << std::endl; - std::cout << "AVC Total bytes received " << abytes_received << std::endl; + std::cout << "Video Total bytes received " << abytes_received << std::endl; cleanup(ctx, sess, v3c); cleanup(ctx, sess, avc); @@ -95,7 +95,7 @@ void v3c_receive_hook(void* arg, uvgrtp::frame::rtp_frame* frame) } void avc_receive_hook(void* arg, uvgrtp::frame::rtp_frame* frame) { - std::cout << "Received AVC frame, size: " << frame->payload_len << " bytes" << std::endl; + std::cout << "Received video frame, size: " << frame->payload_len << " bytes" << std::endl; abytes_received += frame->payload_len; /* Now we own the frame. Here you could give the frame to the application * if f.ex "arg" was some application-specific pointer diff --git a/examples/v3c_sender.cc b/examples/v3c_sender.cc index 6cf163e..675ceb7 100644 --- a/examples/v3c_sender.cc +++ b/examples/v3c_sender.cc @@ -15,7 +15,7 @@ constexpr int AMOUNT_OF_TEST_PACKETS = 100; constexpr auto END_WAIT = std::chrono::seconds(5); //std::string PATH = "C:\\Users\\ngheta\\Documents\\TMIV_A3_C_QP3.bit"; -std::string PATH = "C:\\Users\\ngheta\\Documents\\test_seq3.vpcc"; +std::string PATH = "C:\\Users\\ngheta\\Documents\\v3c_test_seq_2.vpcc"; int main(void) { @@ -23,51 +23,57 @@ int main(void) /* A V3C Sample stream is divided into 6 types of 'sub-bitstreams' + parameters. - The ad_map vector holds the locations and sizes of Atlas NAL units in the file (both AD and CAD) - - The vd_map holds the locations and sizes of all video V3C units (OVD, GVD, AVD, PVD) + - The vd_map holds the locations and sizes of all video NAL units (OVD, GVD, AVD, PVD) - First uint64_t is the start position of the unit, second is the size - With this info you can send the data via different uvgRTP media streams */ std::vector> ad_map = {}; std::vector> vd_map = {}; + /* Fetch the file and its size */ uint64_t len = get_size(PATH); uint64_t ptr = 0; char* cbuf = nullptr; cbuf = get_cmem(PATH, len); + /* Map the locations and sizes of Atlas and video NAL units with the mmap_v3c_file function */ vuh_vps parameters = {}; mmap_v3c_file(cbuf, len, parameters, ad_map, vd_map); std::cout << "Sending Atlas NAL units via uvgRTP" << std::endl; + /* Create the necessary uvgRTP media streams */ uvgrtp::context ctx; uvgrtp::session* sess = ctx.create_session(REMOTE_ADDRESS, REMOTE_ADDRESS); int flags = RCE_SEND_ONLY; uvgrtp::media_stream* v3c = sess->create_stream(8890, 7790, RTP_FORMAT_V3C, flags); - uvgrtp::media_stream* vid = nullptr; + rtp_format_t video_format = RTP_FORMAT_GENERIC; // Create the uvgRTP media stream with the correct RTP format if (parameters.ptl.ptl_profile_codec_group_idc == CODEC_AVC) { std::cout << "Video codec: AVC Progressive High" << std::endl; - vid = sess->create_stream(8892, 7792, RTP_FORMAT_H264, flags); + video_format = RTP_FORMAT_H264; } else if (parameters.ptl.ptl_profile_codec_group_idc == CODEC_HEVC_MAIN10) { std::cout << "Video codec: HEVC Main10" << std::endl; - vid = sess->create_stream(8892, 7792, RTP_FORMAT_H265, flags); + video_format = RTP_FORMAT_H265; } else if (parameters.ptl.ptl_profile_codec_group_idc == CODEC_HEVC444) { std::cout << "Video codec: HEVC444" << std::endl; - vid = sess->create_stream(8892, 7792, RTP_FORMAT_H265, flags); + video_format = RTP_FORMAT_H265; } else if (parameters.ptl.ptl_profile_codec_group_idc == CODEC_VVC_MAIN10) { std::cout << "Video codec: VVC Main10" << std::endl; - vid = sess->create_stream(8892, 7792, RTP_FORMAT_H266, flags); + video_format = RTP_FORMAT_H266; } - + uvgrtp::media_stream* vid = sess->create_stream(8892, 7792, video_format, flags); + uint64_t v3c_bytes_sent = 0; uint64_t avc_bytes_sent = 0; uint64_t send_ptr = 0; + + /* Start sending data. First is all the Atlas NAL units, then all the video NAL units */ for (auto p : ad_map) { std::cout << "Sending frame in location " << p.first << " with size " << p.second << std::endl; @@ -84,7 +90,7 @@ int main(void) { std::cout << "Sending frame in location " << p.first << " with size " << p.second << std::endl; - if (vid->push_frame((uint8_t*)cbuf + p.first, p.second, RTP_NO_FLAGS) != RTP_OK) + if (vid->push_frame((uint8_t*)cbuf + p.first, p.second, RTP_NO_H26X_SCL) != RTP_OK) { std::cout << "Failed to send RTP frame!" << std::endl; } @@ -94,7 +100,7 @@ int main(void) } std::cout << "V3C Sending finished. Total bytes sent " << v3c_bytes_sent << std::endl; - std::cout << "AVC Sending finished. Total bytes sent " << avc_bytes_sent << std::endl; + std::cout << "Video Sending finished. Total bytes sent " << avc_bytes_sent << std::endl; sess->destroy_stream(v3c); sess->destroy_stream(vid); diff --git a/include/uvgrtp/v3c_parser.hh b/include/uvgrtp/v3c_parser.hh index 0b45c30..eb75a5b 100644 --- a/include/uvgrtp/v3c_parser.hh +++ b/include/uvgrtp/v3c_parser.hh @@ -8,7 +8,7 @@ // vuh_unit_type definitions: constexpr int V3C_VPS = 0; // V3C parameter set -constexpr int V3C_AD = 1; // Atlas data +constexpr int V3C_AD = 1; // Atlas data constexpr int V3C_OVD = 2; // Occupancy video data constexpr int V3C_GVD = 3; // Geometry video data constexpr int V3C_AVD = 4; // Attribute video data diff --git a/src/v3c_parser.cc b/src/v3c_parser.cc index 4371abb..a561385 100644 --- a/src/v3c_parser.cc +++ b/src/v3c_parser.cc @@ -34,6 +34,7 @@ bool mmap_v3c_file(char* cbuf, uint64_t len, vuh_vps& param, std::vector sizes = {}; + uint8_t nal_size_precision = 0; while (true) { if (ptr >= len) { break; @@ -53,7 +54,7 @@ bool mmap_v3c_file(char* cbuf, uint64_t len, vuh_vps& param, std::vector> 5) + 1; - std::cout << " -- NAL Sample stream, 1 byte for NAL unit size precision: " << (uint32_t)nal_size_precision << std::endl; - ++v3c_ptr; + if (vuh_t == V3C_AD || vuh_t == V3C_CAD) { + uint8_t v3cu_first_byte = cbuf[v3c_ptr]; // Next up is 1 byte of NAL unit size precision + nal_size_precision = (v3cu_first_byte >> 5) + 1; + std::cout << " -- Atlas NAL Sample stream, 1 byte for NAL unit size precision: " << (uint32_t)nal_size_precision << std::endl; + ++v3c_ptr; + } + else { + nal_size_precision = 4; + std::cout << " -- Video NAL Sample stream, using NAL unit size precision of: " << (uint32_t)nal_size_precision << std::endl; + } // Now start to parse the NAL sample stream while (true) { @@ -100,18 +106,27 @@ bool mmap_v3c_file(char* cbuf, uint64_t len, vuh_vps& param, std::vector> 1; + std::cout << " -- v3c_ptr: " << v3c_ptr << ", NALU size : " << combined_nal_size << ", HEVC NALU type: " << (uint32_t)h265_nalu_t << std::endl; + vd.push_back({ v3c_ptr, combined_nal_size }); } v3c_ptr += combined_nal_size; }