/*************************************************************************************** * * 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-2024, 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 "util.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; } 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->chroma_format_idc > 3) { log_print(HT_LOG_ERR, "%s, chroma_format_idc[%d]!!!\r\n", __FUNCTION__, 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; } void hvcc_init(HEVCDecoderConfigurationRecord * hvcc) { memset(hvcc, 0, sizeof(HEVCDecoderConfigurationRecord)); hvcc->lengthSizeMinusOne = 3; // 4 bytes /* * The following fields have all their valid bits set by default, * the ProfileTierLevel parsing code will unset them when needed. */ hvcc->general_profile_compatibility_flags = 0xffffffff; hvcc->general_constraint_indicator_flags = 0xffffffffffff; /* * Initialize this field with an invalid value which can be used to detect * whether we didn't see any VUI (in which case it should be reset to zero). */ hvcc->min_spatial_segmentation_idc = MAX_SPATIAL_SEGMENTATION + 1; } int hvcc_parse_vps(HEVCDecoderConfigurationRecord * hvcc, uint8 * p_data, int len) { uint32 vps_max_sub_layers_minus1; uint8 bufs[512]; bs_t s; if (len > (int)sizeof(bufs)) { return -1; } len = h265_extract_rbsp(p_data, len, bufs); bs_init(&s, bufs, len); /* * vps_video_parameter_set_id u(4) * vps_reserved_three_2bits u(2) * vps_max_layers_minus1 u(6) */ bs_skip(&s, 12); vps_max_sub_layers_minus1 = bs_read(&s, 3); /* * numTemporalLayers greater than 1 indicates that the stream to which this * configuration record applies is temporally scalable and the contained * number of temporal layers (also referred to as temporal sub-layer or * sub-layer in ISO/IEC 23008-2) is equal to numTemporalLayers. Value 1 * indicates that the stream is not temporally scalable. Value 0 indicates * that it is unknown whether the stream is temporally scalable. */ hvcc->numTemporalLayers = MAX(hvcc->numTemporalLayers, vps_max_sub_layers_minus1 + 1); /* * vps_temporal_id_nesting_flag u(1) * vps_reserved_0xffff_16bits u(16) */ bs_skip(&s, 17); uint8 profile_space; uint8 tier_flag; uint8 profile_idc; uint32 profile_compatibility_flags; uint64 constraint_indicator_flags; uint8 level_idc; profile_space = bs_read(&s, 2); tier_flag = bs_read(&s, 1); profile_idc = bs_read(&s, 5); profile_compatibility_flags = bs_read(&s, 32); constraint_indicator_flags = (uint64)bs_read(&s, 16) << 32; constraint_indicator_flags |= bs_read(&s, 32); level_idc = bs_read(&s, 8); hvcc->general_profile_space = profile_space; /* * The level indication general_level_idc must indicate a level of * capability equal to or greater than the highest level indicated for the * highest tier in all the parameter sets. */ if (hvcc->general_tier_flag < tier_flag) hvcc->general_level_idc = level_idc; else hvcc->general_level_idc = MAX(hvcc->general_level_idc, level_idc); /* * The tier indication general_tier_flag must indicate a tier equal to or * greater than the highest tier indicated in all the parameter sets. */ hvcc->general_tier_flag = MAX(hvcc->general_tier_flag, tier_flag); /* * The profile indication general_profile_idc must indicate a profile to * which the stream associated with this configuration record conforms. * * If the sequence parameter sets are marked with different profiles, then * the stream may need examination to determine which profile, if any, the * entire stream conforms to. If the entire stream is not examined, or the * examination reveals that there is no profile to which the entire stream * conforms, then the entire stream must be split into two or more * sub-streams with separate configuration records in which these rules can * be met. * * Note: set the profile to the highest value for the sake of simplicity. */ hvcc->general_profile_idc = MAX(hvcc->general_profile_idc, profile_idc); /* * Each bit in general_profile_compatibility_flags may only be set if all * the parameter sets set that bit. */ hvcc->general_profile_compatibility_flags &= profile_compatibility_flags; /* * Each bit in general_constraint_indicator_flags may only be set if all * the parameter sets set that bit. */ hvcc->general_constraint_indicator_flags &= constraint_indicator_flags; /* nothing useful for hvcC past this point */ return 0; } int hvcc_parse_pps(HEVCDecoderConfigurationRecord * hvcc, uint8 * p_data, int len) { uint8 tiles_enabled_flag, entropy_coding_sync_enabled_flag; uint8 bufs[512]; bs_t s; if (len > (int)sizeof(bufs)) { return -1; } len = h265_extract_rbsp(p_data, len, bufs); bs_init(&s, bufs, len); bs_read_ue(&s); // pps_pic_parameter_set_id bs_read_ue(&s); // pps_seq_parameter_set_id /* * dependent_slice_segments_enabled_flag u(1) * output_flag_present_flag u(1) * num_extra_slice_header_bits u(3) * sign_data_hiding_enabled_flag u(1) * cabac_init_present_flag u(1) */ bs_skip(&s, 7); bs_read_ue(&s); // num_ref_idx_l0_default_active_minus1 bs_read_ue(&s); // num_ref_idx_l1_default_active_minus1 bs_read_se(&s); // init_qp_minus26 /* * constrained_intra_pred_flag u(1) * transform_skip_enabled_flag u(1) */ bs_skip(&s, 2); if (bs_read(&s, 1)) // cu_qp_delta_enabled_flag bs_read_ue(&s); // diff_cu_qp_delta_depth bs_read_se(&s); // pps_cb_qp_offset bs_read_se(&s); // pps_cr_qp_offset /* * pps_slice_chroma_qp_offsets_present_flag u(1) * weighted_pred_flag u(1) * weighted_bipred_flag u(1) * transquant_bypass_enabled_flag u(1) */ bs_skip(&s, 4); tiles_enabled_flag = bs_read(&s, 1); entropy_coding_sync_enabled_flag = bs_read(&s, 1); if (entropy_coding_sync_enabled_flag && tiles_enabled_flag) hvcc->parallelismType = 0; // mixed-type parallel decoding else if (entropy_coding_sync_enabled_flag) hvcc->parallelismType = 3; // wavefront-based parallel decoding else if (tiles_enabled_flag) hvcc->parallelismType = 2; // tile-based parallel decoding else hvcc->parallelismType = 1; // slice-based parallel decoding /* nothing useful for hvcC past this point */ return 0; }