v3c: Add parsing of the profile_tier_level fields in V3C VPS units
This commit is contained in:
parent
1d5d1fa1a9
commit
0e8c52aa77
|
@ -42,7 +42,7 @@ int main(void)
|
||||||
|
|
||||||
uvgrtp::context ctx;
|
uvgrtp::context ctx;
|
||||||
uvgrtp::session* sess = ctx.create_session(LOCAL_ADDRESS, LOCAL_ADDRESS);
|
uvgrtp::session* sess = ctx.create_session(LOCAL_ADDRESS, LOCAL_ADDRESS);
|
||||||
int flags = RCE_RECEIVE_ONLY;
|
int flags = RCE_RECEIVE_ONLY | RCE_NO_H26X_PREPEND_SC;
|
||||||
uvgrtp::media_stream* v3c = sess->create_stream(7790, 8890, RTP_FORMAT_V3C, flags);
|
uvgrtp::media_stream* v3c = sess->create_stream(7790, 8890, RTP_FORMAT_V3C, flags);
|
||||||
uvgrtp::media_stream* avc = sess->create_stream(7792, 8892, RTP_FORMAT_H265, flags);
|
uvgrtp::media_stream* avc = sess->create_stream(7792, 8892, RTP_FORMAT_H265, flags);
|
||||||
vbytes_received = 0;
|
vbytes_received = 0;
|
||||||
|
@ -74,6 +74,7 @@ int main(void)
|
||||||
std::this_thread::sleep_for(RECEIVE_TIME_S); // lets this example run for some time
|
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 << "V3C Total bytes received " << vbytes_received << std::endl;
|
||||||
std::cout << "Video Total bytes received " << abytes_received << std::endl;
|
std::cout << "Video Total bytes received " << abytes_received << std::endl;
|
||||||
|
std::cout << "All Total bytes received " << abytes_received + vbytes_received << std::endl;
|
||||||
|
|
||||||
cleanup(ctx, sess, v3c);
|
cleanup(ctx, sess, v3c);
|
||||||
cleanup(ctx, sess, avc);
|
cleanup(ctx, sess, avc);
|
||||||
|
|
|
@ -14,8 +14,8 @@ constexpr size_t PAYLOAD_LEN = 100;
|
||||||
constexpr int AMOUNT_OF_TEST_PACKETS = 100;
|
constexpr int AMOUNT_OF_TEST_PACKETS = 100;
|
||||||
constexpr auto END_WAIT = std::chrono::seconds(5);
|
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\\TMIV_A3_C_QP3.bit";
|
||||||
std::string PATH = "C:\\Users\\ngheta\\Documents\\test_seq3.vpcc";
|
//std::string PATH = "C:\\Users\\ngheta\\Documents\\test_seq3.vpcc";
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
|
@ -23,11 +23,14 @@ int main(void)
|
||||||
|
|
||||||
/* A V3C Sample stream is divided into 6 types of 'sub-bitstreams' + parameters.
|
/* A V3C Sample stream is divided into 6 types of 'sub-bitstreams' + parameters.
|
||||||
- The nal_map holds nal_info structs
|
- The nal_map holds nal_info structs
|
||||||
- nal_info struct holds the format(V3C, H264, H265, H266), start position and size of the NAL 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. 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_V3C for
|
||||||
Atlas NAL units and a second one for the video NAL units in the correct format*/
|
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 */
|
||||||
|
|
||||||
std::vector<nal_info> nal_map = {};
|
std::vector<nal_info> nal_map = {};
|
||||||
|
std::vector<vuh_vps> vps_map = {};
|
||||||
|
|
||||||
/* Fetch the file and its size */
|
/* Fetch the file and its size */
|
||||||
uint64_t len = get_size(PATH);
|
uint64_t len = get_size(PATH);
|
||||||
|
@ -36,8 +39,7 @@ int main(void)
|
||||||
cbuf = get_cmem(PATH, len);
|
cbuf = get_cmem(PATH, len);
|
||||||
|
|
||||||
/* Map the locations and sizes of Atlas and video NAL units with the mmap_v3c_file function */
|
/* 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, nal_map, vps_map);
|
||||||
mmap_v3c_file(cbuf, len, parameters, nal_map);
|
|
||||||
|
|
||||||
std::cout << "Sending Atlas NAL units via uvgRTP" << std::endl;
|
std::cout << "Sending Atlas NAL units via uvgRTP" << std::endl;
|
||||||
|
|
||||||
|
@ -49,19 +51,19 @@ int main(void)
|
||||||
rtp_format_t video_format = RTP_FORMAT_GENERIC;
|
rtp_format_t video_format = RTP_FORMAT_GENERIC;
|
||||||
|
|
||||||
// Create the uvgRTP media stream with the correct RTP format
|
// Create the uvgRTP media stream with the correct RTP format
|
||||||
if (parameters.ptl.ptl_profile_codec_group_idc == CODEC_AVC) {
|
if (vps_map.begin()->ptl.ptl_profile_codec_group_idc == CODEC_AVC) {
|
||||||
std::cout << "Video codec: AVC Progressive High" << std::endl;
|
std::cout << "Video codec: AVC Progressive High" << std::endl;
|
||||||
video_format = RTP_FORMAT_H264;
|
video_format = RTP_FORMAT_H264;
|
||||||
}
|
}
|
||||||
else if (parameters.ptl.ptl_profile_codec_group_idc == CODEC_HEVC_MAIN10) {
|
else if (vps_map.begin()->ptl.ptl_profile_codec_group_idc == CODEC_HEVC_MAIN10) {
|
||||||
std::cout << "Video codec: HEVC Main10" << std::endl;
|
std::cout << "Video codec: HEVC Main10" << std::endl;
|
||||||
video_format = RTP_FORMAT_H265;
|
video_format = RTP_FORMAT_H265;
|
||||||
}
|
}
|
||||||
else if (parameters.ptl.ptl_profile_codec_group_idc == CODEC_HEVC444) {
|
else if (vps_map.begin()->ptl.ptl_profile_codec_group_idc == CODEC_HEVC444) {
|
||||||
std::cout << "Video codec: HEVC444" << std::endl;
|
std::cout << "Video codec: HEVC444" << std::endl;
|
||||||
video_format = RTP_FORMAT_H265;
|
video_format = RTP_FORMAT_H265;
|
||||||
}
|
}
|
||||||
else if (parameters.ptl.ptl_profile_codec_group_idc == CODEC_VVC_MAIN10) {
|
else if (vps_map.begin()->ptl.ptl_profile_codec_group_idc == CODEC_VVC_MAIN10) {
|
||||||
std::cout << "Video codec: VVC Main10" << std::endl;
|
std::cout << "Video codec: VVC Main10" << std::endl;
|
||||||
video_format = RTP_FORMAT_H266;
|
video_format = RTP_FORMAT_H266;
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,14 @@ constexpr uint8_t VVC_SC = 0x00000001; // VVC Start Code
|
||||||
struct profile_tier_level {
|
struct profile_tier_level {
|
||||||
uint8_t ptl_tier_flag = 0;
|
uint8_t ptl_tier_flag = 0;
|
||||||
uint8_t ptl_profile_codec_group_idc = 0;
|
uint8_t ptl_profile_codec_group_idc = 0;
|
||||||
|
uint8_t ptl_profile_toolset_idc = 0;
|
||||||
|
uint8_t ptl_profile_reconstruction_idc = 0;
|
||||||
|
uint8_t ptl_max_decodes_idc = 0;
|
||||||
|
uint8_t ptl_level_idc = 0;
|
||||||
|
uint8_t ptl_num_sub_profiles = 0;
|
||||||
|
bool ptl_extended_sub_profile_flag = 0;
|
||||||
|
std::vector<uint64_t> ptl_sub_profile_idc;
|
||||||
|
bool ptl_toolset_constraints_present_flag = 0;
|
||||||
};
|
};
|
||||||
struct vuh_vps {
|
struct vuh_vps {
|
||||||
profile_tier_level ptl;
|
profile_tier_level ptl;
|
||||||
|
@ -72,6 +80,10 @@ struct v3c_unit_header {
|
||||||
vuh_pvd pvd;
|
vuh_pvd pvd;
|
||||||
vuh_cad cad;
|
vuh_cad cad;
|
||||||
};
|
};
|
||||||
|
~v3c_unit_header() {
|
||||||
|
vps.~vuh_vps();
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct nal_info {
|
struct nal_info {
|
||||||
|
@ -88,5 +100,5 @@ uint64_t get_size(std::string filename);
|
||||||
char* get_cmem(std::string filename, const size_t& len);
|
char* get_cmem(std::string filename, const size_t& len);
|
||||||
|
|
||||||
// ad is for AD and CAD substreams, vd is for all VD substreams
|
// ad is for AD and CAD substreams, vd is for all VD substreams
|
||||||
bool mmap_v3c_file(char* cbuf, uint64_t len, vuh_vps& param, std::vector<nal_info>& nal_map);
|
bool mmap_v3c_file(char* cbuf, uint64_t len, std::vector<nal_info>& nal_map, std::vector<vuh_vps> &vps_map);
|
||||||
void parse_v3c_header(v3c_unit_header &hdr, char* buf, uint64_t ptr);
|
void parse_v3c_header(v3c_unit_header &hdr, char* buf, uint64_t ptr);
|
|
@ -18,7 +18,7 @@ uint32_t combineBytes(uint8_t byte1, uint8_t byte2) {
|
||||||
(static_cast<uint32_t>(byte2));
|
(static_cast<uint32_t>(byte2));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mmap_v3c_file(char* cbuf, uint64_t len, vuh_vps& param, std::vector<nal_info>& nal_map)
|
bool mmap_v3c_file(char* cbuf, uint64_t len, std::vector<nal_info>& nal_map, std::vector<vuh_vps>& vps_map)
|
||||||
{
|
{
|
||||||
uint64_t ptr = 0;
|
uint64_t ptr = 0;
|
||||||
|
|
||||||
|
@ -32,7 +32,6 @@ bool mmap_v3c_file(char* cbuf, uint64_t len, vuh_vps& param, std::vector<nal_inf
|
||||||
|
|
||||||
uint8_t* v3c_size = new uint8_t[v3c_size_precision];
|
uint8_t* v3c_size = new uint8_t[v3c_size_precision];
|
||||||
|
|
||||||
std::vector<uint32_t> sizes = {};
|
|
||||||
uint8_t nal_size_precision = 0;
|
uint8_t nal_size_precision = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
if (ptr >= len) {
|
if (ptr >= len) {
|
||||||
|
@ -66,18 +65,12 @@ bool mmap_v3c_file(char* cbuf, uint64_t len, vuh_vps& param, std::vector<nal_inf
|
||||||
// Parameter set contains no NAL units, skip over
|
// Parameter set contains no NAL units, skip over
|
||||||
std::cout << "-- Parameter set V3C unit" << std::endl;
|
std::cout << "-- Parameter set V3C unit" << std::endl;
|
||||||
ptr += combined_v3c_size;
|
ptr += combined_v3c_size;
|
||||||
sizes.push_back(combined_v3c_size);
|
vps_map.push_back(v3c_hdr.vps);
|
||||||
param = v3c_hdr.vps;
|
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (vuh_t == V3C_OVD || vuh_t == V3C_GVD || vuh_t == V3C_AVD || vuh_t == V3C_PVD) {
|
else if (vuh_t == V3C_OVD || vuh_t == V3C_GVD || vuh_t == V3C_AVD || vuh_t == V3C_PVD) {
|
||||||
// Video data, map start and size
|
|
||||||
std::cout << "-- Video data V3C unit, " << std::endl;
|
std::cout << "-- Video data V3C unit, " << std::endl;
|
||||||
//vd.push_back({ ptr + V3C_HDR_LEN, combined_v3c_size });
|
|
||||||
//ptr += combined_v3c_size;
|
|
||||||
//std::cout << std::endl;
|
|
||||||
//continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rest of the function goes inside the V3C unit payload and parses NAL it into NAL units
|
// Rest of the function goes inside the V3C unit payload and parses NAL it into NAL units
|
||||||
|
@ -131,7 +124,6 @@ bool mmap_v3c_file(char* cbuf, uint64_t len, vuh_vps& param, std::vector<nal_inf
|
||||||
|
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
ptr += combined_v3c_size;
|
ptr += combined_v3c_size;
|
||||||
sizes.push_back(combined_v3c_size);
|
|
||||||
}
|
}
|
||||||
std::cout << "File parsed" << std::endl;
|
std::cout << "File parsed" << std::endl;
|
||||||
return true;
|
return true;
|
||||||
|
@ -163,7 +155,7 @@ void parse_v3c_header(v3c_unit_header &hdr, char* buf, uint64_t ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (hdr.vuh_unit_type) {
|
switch (hdr.vuh_unit_type) {
|
||||||
case V3C_VPS:
|
case V3C_VPS: {
|
||||||
hdr.vps = {};
|
hdr.vps = {};
|
||||||
// first bit of first byte
|
// first bit of first byte
|
||||||
hdr.vps.ptl.ptl_tier_flag = buf[ptr + 4] >> 7;
|
hdr.vps.ptl.ptl_tier_flag = buf[ptr + 4] >> 7;
|
||||||
|
@ -171,8 +163,51 @@ void parse_v3c_header(v3c_unit_header &hdr, char* buf, uint64_t ptr)
|
||||||
// 7 bits after
|
// 7 bits after
|
||||||
hdr.vps.ptl.ptl_profile_codec_group_idc = buf[ptr + 4] & 0b01111111;
|
hdr.vps.ptl.ptl_profile_codec_group_idc = buf[ptr + 4] & 0b01111111;
|
||||||
std::cout << "-- ptl_profile_codec_group_idc: " << (uint32_t)hdr.vps.ptl.ptl_profile_codec_group_idc << std::endl;
|
std::cout << "-- ptl_profile_codec_group_idc: " << (uint32_t)hdr.vps.ptl.ptl_profile_codec_group_idc << std::endl;
|
||||||
|
// 8 bits after
|
||||||
|
hdr.vps.ptl.ptl_profile_toolset_idc = buf[ptr + 5];
|
||||||
|
std::cout << "-- ptl_profile_toolset_idc: " << (uint32_t)hdr.vps.ptl.ptl_profile_toolset_idc << std::endl;
|
||||||
|
// 8 bits after
|
||||||
|
hdr.vps.ptl.ptl_profile_reconstruction_idc = buf[ptr + 6];
|
||||||
|
std::cout << "-- ptl_profile_reconstruction_idc: " << (uint32_t)hdr.vps.ptl.ptl_profile_reconstruction_idc << std::endl;
|
||||||
|
// 16 reserved bits
|
||||||
|
//4 bits after
|
||||||
|
hdr.vps.ptl.ptl_max_decodes_idc = buf[ptr + 9] >> 4;
|
||||||
|
std::cout << "-- ptl_max_decodes_idc: " << (uint32_t)hdr.vps.ptl.ptl_max_decodes_idc << "+1 = " <<
|
||||||
|
(uint32_t)hdr.vps.ptl.ptl_max_decodes_idc + 1 << std::endl;
|
||||||
|
// 12 reserved bits
|
||||||
|
// 8 bits after
|
||||||
|
hdr.vps.ptl.ptl_level_idc = buf[ptr + 11];
|
||||||
|
std::cout << "-- ptl_level_idc: " << (uint32_t)hdr.vps.ptl.ptl_level_idc << "/30 = " <<
|
||||||
|
(double)hdr.vps.ptl.ptl_level_idc / 30 << std::endl;
|
||||||
|
// 6 bits after
|
||||||
|
hdr.vps.ptl.ptl_num_sub_profiles = buf[ptr + 12] >> 2;
|
||||||
|
std::cout << "-- ptl_num_sub_profiles: " << (uint32_t)hdr.vps.ptl.ptl_num_sub_profiles << std::endl;
|
||||||
|
// 1 bit after
|
||||||
|
hdr.vps.ptl.ptl_extended_sub_profile_flag = (buf[ptr + 12] & 0b10) >> 1;
|
||||||
|
std::cout << "-- ptl_extended_sub_profile_flag: " << (uint32_t)hdr.vps.ptl.ptl_extended_sub_profile_flag << std::endl;
|
||||||
|
// next up are the sub-profile IDs. They can be either 32 or 64 bits long, indicated by ptl_extended_sub_profile_flag
|
||||||
|
// Note: This has not been tested. But it should work
|
||||||
|
ptr += 12;
|
||||||
|
uint64_t first_full_byte = ptr + 13;
|
||||||
|
if (hdr.vps.ptl.ptl_extended_sub_profile_flag == 1) {
|
||||||
|
for (int i = 0; i < hdr.vps.ptl.ptl_num_sub_profiles; i++) {
|
||||||
|
uint64_t sub_profile_id = (buf[first_full_byte] >> 1) | ((buf[first_full_byte - 1] & 0b1) << 63);
|
||||||
|
hdr.vps.ptl.ptl_sub_profile_idc.push_back(sub_profile_id);
|
||||||
|
first_full_byte += 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (int i = 0; i < hdr.vps.ptl.ptl_num_sub_profiles; i++) {
|
||||||
|
uint32_t sub_profile_id = (buf[first_full_byte] >> 1) | ((buf[first_full_byte - 1] & 0b1) << 31);
|
||||||
|
hdr.vps.ptl.ptl_sub_profile_idc.push_back((uint64_t)sub_profile_id);
|
||||||
|
first_full_byte += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 1 bit after
|
||||||
|
hdr.vps.ptl.ptl_toolset_constraints_present_flag = (buf[ptr] & 0b1);
|
||||||
|
std::cout << "-- ptl_toolset_constraints_present_flag: " << (uint32_t)hdr.vps.ptl.ptl_toolset_constraints_present_flag << std::endl;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case V3C_AD:
|
case V3C_AD:
|
||||||
hdr.ad = {};
|
hdr.ad = {};
|
||||||
hdr.ad.vuh_v3c_parameter_set_id = vuh_v3c_parameter_set_id;
|
hdr.ad.vuh_v3c_parameter_set_id = vuh_v3c_parameter_set_id;
|
||||||
|
|
Loading…
Reference in New Issue