/*************************************************************************************** * * IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. * * By downloading, copying, installing or using the software you agree to this license. * If you do not agree to this license, do not download, install, * copy or use the software. * * Copyright (C) 2014-2022, Happytimesoft Corporation, all rights reserved. * * Redistribution and use in binary forms, with or without modification, are permitted. * * Unless required by applicable law or agreed to in writing, software distributed * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific * language governing permissions and limitations under the License. * ****************************************************************************************/ #include "sys_inc.h" #include "bs.h" #include "h265.h" #include "h265_util.h" int h265_extract_rbsp(const uint8 *src, int length, uint8 *dst) { int i, si, di; for (i = 0; i + 1 < length; i += 2) { if (src[i]) { continue; } if (i > 0 && src[i - 1] == 0) { i--; } if (i + 2 < length && src[i + 1] == 0 && src[i + 2] <= 3) { if (src[i + 2] != 3 && src[i + 2] != 0) { /* startcode, so we must be past the end */ length = i; } break; } } if (i >= length - 1) { // no escaped 0 memcpy(dst, src, length); return length; } else if (i > length) { i = length; } memcpy(dst, src, i); si = di = i; while (si + 2 < length) { // remove escapes (very rare 1:2^22) if (src[si + 2] > 3) { dst[di++] = src[si++]; dst[di++] = src[si++]; } else if (src[si] == 0 && src[si + 1] == 0 && src[si + 2] != 0) { if (src[si + 2] == 3) { // escape dst[di++] = 0; dst[di++] = 0; si += 3; continue; } else // next start code { return si; } } dst[di++] = src[si++]; } while (si < length) { dst[di++] = src[si++]; } return si; } void h265_parser_init(h265_t * h) { memset(h, 0, sizeof(h265_t)); } int h265_parser_parse(h265_t * h, uint8 * p_data, int len) { uint32 i; bs_t s; uint8 bufs[512]; if (len > (int)sizeof(bufs)) { return -1; } len = h265_extract_rbsp(p_data, len, bufs); bs_init(&s, bufs, len); bs_read(&s, 4); // sps_video_parameter_set_id u(4) h->sps_max_sub_layers_minus1 = bs_read(&s, 3); // sps_max_sub_layers_minus1 u(3) if (h->sps_max_sub_layers_minus1 > 6) { log_print(HT_LOG_ERR, "%s, sps_max_sub_layers_minus1[%d]>6!!!\r\n", __FUNCTION__, h->sps_max_sub_layers_minus1); return -1; } bs_read(&s, 1); // sps_temporal_id_nesting_flag u(1) // profile_tier_level( maxNumSubLayersMinus1 ) { bs_read(&s, 2); // general_profile_space u(2) bs_read(&s, 1); // general_tier_flag u(1) h->general_profile_idc = bs_read(&s, 5); // general_profile_idc u(5) bs_read(&s, 32); // general_profile_compatibility_flag[ j ] u(5) bs_read(&s, 1); // general_progressive_source_flag u(1) bs_read(&s, 1); // general_interlaced_source_flag u(1) bs_read(&s, 1); // general_non_packed_constraint_flag u(1) bs_read(&s, 1); // general_frame_only_constraint_flag u(1) bs_skip(&s, 44); // general_reserved_zero_44bits u(44) h->general_level_idc = bs_read(&s, 8); // general_level_idc u(8) uint8 sub_layer_profile_present_flag[6] = {0}; uint8 sub_layer_level_present_flag[6] = {0}; for (i = 0; i < h->sps_max_sub_layers_minus1; i++) { sub_layer_profile_present_flag[i]= bs_read(&s, 1); sub_layer_level_present_flag[i]= bs_read(&s, 1); } if (h->sps_max_sub_layers_minus1 > 0) { for (i = h->sps_max_sub_layers_minus1; i < 8; i++) { bs_read(&s, 2); } } for (i = 0; i < h->sps_max_sub_layers_minus1; i++) { if (sub_layer_profile_present_flag[i]) { bs_read(&s, 2); // sub_layer_profile_space[i] bs_read(&s, 1); // sub_layer_tier_flag[i] bs_read(&s, 5); // sub_layer_profile_idc[i] bs_read(&s, 32); // sub_layer_profile_compatibility_flag[i][32] bs_read(&s, 1); // sub_layer_progressive_source_flag[i] bs_read(&s, 1); // sub_layer_interlaced_source_flag[i] bs_read(&s, 1); // sub_layer_non_packed_constraint_flag[i] bs_read(&s, 1); // sub_layer_frame_only_constraint_flag[i] bs_read(&s, 44); // sub_layer_reserved_zero_44bits[i] } if (sub_layer_level_present_flag[i]) { bs_read(&s, 8); // sub_layer_level_idc[i] } } } h->sps_seq_parameter_set_id = bs_read_ue(&s); // sps_seq_parameter_set_id ue(v) h->chroma_format_idc = bs_read_ue(&s); // chroma_format_idc ue(v) if (h->sps_seq_parameter_set_id > 15 || h->chroma_format_idc > 3) { log_print(HT_LOG_ERR, "%s, sps_seq_parameter_set_id[%d],chroma_format_idc[%d]!!!\r\n", __FUNCTION__, h->sps_seq_parameter_set_id, h->chroma_format_idc); return -1; } if (h->chroma_format_idc == 3) { h->separate_colour_plane_flag = bs_read(&s, 1); // separate_colour_plane_flag } h->pic_width_in_luma_samples = bs_read_ue(&s); // pic_width_in_luma_samples ue(v) h->pic_height_in_luma_samples = bs_read_ue(&s); // pic_height_in_luma_samples ue(v) h->conformance_window_flag = bs_read(&s, 1 ); // conformance_window_flag u(1) if (h->conformance_window_flag) { h->conf_win_left_offset = bs_read_ue(&s); // conf_win_left_offset ue(v) h->conf_win_right_offset = bs_read_ue(&s); // conf_win_right_offset ue(v) h->conf_win_top_offset = bs_read_ue(&s); // conf_win_top_offset ue(v) h->conf_win_bottom_offset = bs_read_ue(&s); // conf_win_bottom_offset ue(v) } h->bit_depth_luma_minus8 = bs_read_ue(&s); // bit_depth_luma_minus8 ue(v) h->bit_depth_chroma_minus8 = bs_read_ue(&s); // bit_depth_chroma_minus8 ue(v) return 0; }