#include #include "v3c/v3c_util.hh" #include #include #include constexpr char LOCAL_ADDRESS[] = "127.0.0.1"; // This example runs for 5 seconds constexpr auto RECEIVE_TIME_S = std::chrono::seconds(10); void vps_receive_hook(void* arg, uvgrtp::frame::rtp_frame* frame); void ad_receive_hook(void* arg, uvgrtp::frame::rtp_frame* frame); void ovd_receive_hook(void* arg, uvgrtp::frame::rtp_frame* frame); void gvd_receive_hook(void* arg, uvgrtp::frame::rtp_frame* frame); void avd_receive_hook(void* arg, uvgrtp::frame::rtp_frame* frame); uint64_t vps_count; /* 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; /* 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) { std::cout << "Starting uvgRTP V3C receive hook example" << std::endl; /* Fetch the original file and its size */ uint64_t len = get_size(PATH); std::cout << "File size " << len << std::endl; char* original_buf = nullptr; original_buf = get_cmem(PATH); uvgrtp::context ctx; uvgrtp::session* sess = ctx.create_session(LOCAL_ADDRESS, LOCAL_ADDRESS); int flags = RCE_RECEIVE_ONLY; // Create the uvgRTP media streams with the correct RTP format v3c_streams streams = init_v3c_streams(sess, 8890, 8892, flags, true); // Initialize memory map v3c_file_map mmap = init_mmap(); streams.vps->install_receive_hook(&mmap.vps_units, vps_receive_hook); streams.ad->install_receive_hook(&mmap.ad_units, ad_receive_hook); 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 = 0; uint64_t bytes = 0; uint64_t ptr = 0; bool hdb = true; 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)) { //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 } std::this_thread::sleep_for(std::chrono::milliseconds(10)); } std::this_thread::sleep_for(RECEIVE_TIME_S); // lets this example run for some time sess->destroy_stream(streams.vps); sess->destroy_stream(streams.ad); sess->destroy_stream(streams.ovd); sess->destroy_stream(streams.gvd); sess->destroy_stream(streams.avd); ctx.destroy_session(sess); // compare files for (auto i = 0; i < len; ++i) { if (original_buf[i] != out_buf[i]) { std::cout << "Difference at " << i << std::endl; break; } } std::cout << "Done " << std::endl; return EXIT_SUCCESS; } void vps_receive_hook(void* arg, uvgrtp::frame::rtp_frame* frame) { std::vector* vec = (std::vector*)arg; char* cbuf = new char[frame->payload_len]; memcpy(cbuf, frame->payload, frame->payload_len); v3c_unit_info vps = { {}, {{0, frame->payload_len}}, cbuf }; vec->push_back(vps); (void)uvgrtp::frame::dealloc_frame(frame); } void ad_receive_hook(void* arg, uvgrtp::frame::rtp_frame* frame) { std::vector* vec = (std::vector*)arg; copy_rtp_payload(*vec, AD_NALS, frame); (void)uvgrtp::frame::dealloc_frame(frame); } void ovd_receive_hook(void* arg, uvgrtp::frame::rtp_frame* frame) { std::vector* vec = (std::vector*)arg; copy_rtp_payload(*vec, OVD_NALS, frame); (void)uvgrtp::frame::dealloc_frame(frame); } void gvd_receive_hook(void* arg, uvgrtp::frame::rtp_frame* frame) { std::vector* vec = (std::vector*)arg; copy_rtp_payload(*vec, GVD_NALS, frame); (void)uvgrtp::frame::dealloc_frame(frame); } void avd_receive_hook(void* arg, uvgrtp::frame::rtp_frame* frame) { std::vector* vec = (std::vector*)arg; copy_rtp_payload(*vec, AVD_NALS, frame); (void)uvgrtp::frame::dealloc_frame(frame); }