/*************************************************************************************** ***************************************************************************************/ #include #include #include #include /* for uint32_t, etc */ #include "sps_pps.h" /* report level */ #define RPT_ERR (1) // error, system error #define RPT_WRN (2) // warning, maybe wrong, maybe OK #define RPT_INF (3) // important information #define RPT_DBG (4) // debug information static int rpt_lvl = RPT_WRN; /* report level: ERR, WRN, INF, DBG */ /* report micro */ #define RPT(lvl, ...) \ do { \ if(lvl <= rpt_lvl) { \ switch(lvl) { \ case RPT_ERR: \ fprintf(stderr, "\"%s\" line %d [err]: ", __FILE__, __LINE__); \ break; \ case RPT_WRN: \ fprintf(stderr, "\"%s\" line %d [wrn]: ", __FILE__, __LINE__); \ break; \ case RPT_INF: \ fprintf(stderr, "\"%s\" line %d [inf]: ", __FILE__, __LINE__); \ break; \ case RPT_DBG: \ fprintf(stderr, "\"%s\" line %d [dbg]: ", __FILE__, __LINE__); \ break; \ default: \ fprintf(stderr, "\"%s\" line %d [???]: ", __FILE__, __LINE__); \ break; \ } \ fprintf(stderr, __VA_ARGS__); \ fprintf(stderr, "\n"); \ } \ } while(0) /******************************************** *define here ********************************************/ #define SPS_PPS_DEBUG #undef SPS_PPS_DEBUG #define MAX_LEN 32 /******************************************** *functions ********************************************/ /** * @brief Function get_1bit() ¶Á1¸öbit * @param[in] h get_bit_context structrue * @retval 0: success, -1 : failure * @pre * @post */ static int get_1bit(void *h) { get_bit_context *ptr = (get_bit_context *)h; int ret = 0; uint8_t *cur_char = NULL; uint8_t shift; if(NULL == ptr) { RPT(RPT_ERR, "NULL pointer"); ret = -1; goto exit; } cur_char = ptr->buf + (ptr->bit_pos >> 3); shift = 7 - (ptr->cur_bit_pos); ptr->bit_pos++; ptr->cur_bit_pos = ptr->bit_pos & 0x7; ret = ((*cur_char) >> shift) & 0x01; exit: return ret; } /** * @brief Function get_bits() ¶Án¸öbits£¬n²»Äܳ¬¹ý32 * @param[in] h get_bit_context structrue * @param[in] n how many bits you want? * @retval 0: success, -1 : failure * @pre * @post */ static int get_bits(void *h, int n) { get_bit_context *ptr = (get_bit_context *)h; uint8_t temp[5] = {0}; uint8_t *cur_char = NULL; uint8_t nbyte; uint8_t shift; uint32_t result; uint64_t ret = 0; if(NULL == ptr) { RPT(RPT_ERR, "NULL pointer"); ret = -1; goto exit; } if(n > MAX_LEN) { n = MAX_LEN; } if((ptr->bit_pos + n) > ptr->total_bit) { n = ptr->total_bit- ptr->bit_pos; } cur_char = ptr->buf+ (ptr->bit_pos>>3); nbyte = (ptr->cur_bit_pos + n + 7) >> 3; shift = (8 - (ptr->cur_bit_pos + n))& 0x07; if(n == MAX_LEN) { RPT(RPT_DBG, "12(ptr->bit_pos(:%d) + n(:%d)) > ptr->total_bit(:%d)!!! ",\ ptr->bit_pos, n, ptr->total_bit); RPT(RPT_DBG, "0x%x 0x%x 0x%x 0x%x", (*cur_char), *(cur_char+1),*(cur_char+2),*(cur_char+3)); } memcpy(&temp[5-nbyte], cur_char, nbyte); ret = (uint32_t)temp[0] << 24; ret = ret << 8; ret = ((uint32_t)temp[1]<<24)|((uint32_t)temp[2] << 16)\ |((uint32_t)temp[3] << 8)|temp[4]; ret = (ret >> shift) & (((uint64_t)1<bit_pos += n; ptr->cur_bit_pos = ptr->bit_pos & 0x7; exit: return result; } /** * @brief Function parse_codenum() Ö¸Êý¸çÂײ¼±àÂë½âÎö£¬²Î¿¼h264±ê×¼µÚ9½Ú * @param[in] buf * @retval code_num * @pre * @post */ static int parse_codenum(void *buf) { uint8_t leading_zero_bits = -1; uint8_t b; uint32_t code_num = 0; for(b=0; !b; leading_zero_bits++) { b = get_1bit(buf); } code_num = ((uint32_t)1 << leading_zero_bits) - 1 + get_bits(buf, leading_zero_bits); return code_num; } /** * @brief Function parse_ue() Ö¸Êý¸çÂײ¼±àÂë½âÎö ue(),²Î¿¼h264±ê×¼µÚ9½Ú * @param[in] buf sps_pps parse buf * @retval code_num * @pre * @post */ static int parse_ue(void *buf) { return parse_codenum(buf); } /** * @brief Function parse_se() Ö¸Êý¸çÂײ¼±àÂë½âÎö se(), ²Î¿¼h264±ê×¼µÚ9½Ú * @param[in] buf sps_pps parse buf * @retval code_num * @pre * @post */ static int parse_se(void *buf) { int ret = 0; int code_num; code_num = parse_codenum(buf); ret = (code_num + 1) >> 1; ret = (code_num & 0x01)? ret : -ret; return ret; } /** * @brief Function get_bit_context_free() ÉêÇëµÄget_bit_context½á¹¹ÄÚ´æÊÍ·Å * @param[in] buf get_bit_context buf * @retval none * @pre * @post */ static void get_bit_context_free(void *buf) { get_bit_context *ptr = (get_bit_context *)buf; if(ptr) { if(ptr->buf) { free(ptr->buf); } free(ptr); } } /** * @brief Function de_emulation_prevention() ½â¾ºÕù´úÂë * @param[in] buf get_bit_context buf * @retval none * @pre * @post * @note: * µ÷ÊÔʱ×ÜÊÇ·¢ÏÖvui.time_scaleÖµÌØ±ðÆæ¹Ö£¬×ÜÊÇ16777216£¬ºóÀ´²éѯԭÒòÈçÏÂ: * http://www.cnblogs.com/eustoma/archive/2012/02/13/2415764.html * H.264±àÂëʱ£¬ÔÚÿ¸öNALǰÌí¼ÓÆðʼÂë 0x000001£¬½âÂëÆ÷ÔÚÂëÁ÷Öмì²âµ½ÆðʼÂ룬µ±Ç°NAL½áÊø¡£ * ΪÁË·ÀÖ¹NALÄÚ²¿³öÏÖ0x000001µÄÊý¾Ý£¬h.264ÓÖÌá³ö'·ÀÖ¹¾ºÕù emulation prevention"»úÖÆ£¬ * ÔÚ±àÂëÍêÒ»¸öNALʱ£¬Èç¹û¼ì²â³öÓÐÁ¬ÐøÁ½¸ö0x00×Ö½Ú£¬¾ÍÔÚºóÃæ²åÈëÒ»¸ö0x03¡£ * µ±½âÂëÆ÷ÔÚNALÄÚ²¿¼ì²âµ½0x000003µÄÊý¾Ý£¬¾Í°Ñ0x03Åׯú£¬»Ö¸´Ô­Ê¼Êý¾Ý¡£ * 0x000000 >>>>>> 0x00000300 * 0x000001 >>>>>> 0x00000301 * 0x000002 >>>>>> 0x00000302 * 0x000003 >>>>>> 0x00000303 */ static void *de_emulation_prevention(void *buf) { get_bit_context *ptr = NULL; get_bit_context *buf_ptr = (get_bit_context *)buf; int i = 0, j = 0; uint8_t *tmp_ptr = NULL; int tmp_buf_size = 0; int val = 0; if(NULL == buf_ptr) { RPT(RPT_ERR, "NULL ptr"); goto exit; } ptr = (get_bit_context *)malloc(sizeof(get_bit_context)); if(NULL == ptr) { RPT(RPT_ERR, "NULL ptr"); goto exit; } memcpy(ptr, buf_ptr, sizeof(get_bit_context)); ptr->buf = (uint8_t *)malloc(ptr->buf_size); if(NULL == ptr->buf) { RPT(RPT_ERR, "NULL ptr"); goto exit; } memcpy(ptr->buf, buf_ptr->buf, buf_ptr->buf_size); tmp_ptr = ptr->buf; tmp_buf_size = ptr->buf_size; for(i=0; i<(tmp_buf_size-2); i++) { /*¼ì²â0x000003*/ val = (tmp_ptr[i]^0x00) + (tmp_ptr[i+1]^0x00) + (tmp_ptr[i+2]^0x03); if(val == 0) { /*ÌÞ³ý0x03*/ for(j=i+2; jbuf_size--; } } /*ÖØÐ¼ÆËãtotal_bit*/ ptr->total_bit = ptr->buf_size << 3; return (void *)ptr; exit: get_bit_context_free(ptr); return NULL; } /** * @brief Function get_bit_context_free() VUI_parameters ½âÎö£¬Ô­Àí²Î¿¼h264±ê×¼ * @param[in] buf get_bit_context buf * @param[in] vui_ptr vui½âÎö½á¹û * @retval 0: success, -1 : failure * @pre * @post */ static int vui_parameters_set(void *buf, vui_parameters_t *vui_ptr) { int ret = 0; int SchedSelIdx = 0; if(NULL == vui_ptr || NULL == buf) { RPT(RPT_ERR,"ERR null pointer\n"); ret = -1; goto exit; } vui_ptr->aspect_ratio_info_present_flag = get_1bit(buf); if(vui_ptr->aspect_ratio_info_present_flag) { vui_ptr->aspect_ratio_idc = get_bits(buf, 8); if(vui_ptr->aspect_ratio_idc == Extended_SAR) { vui_ptr->sar_width = get_bits(buf, 16); vui_ptr->sar_height = get_bits(buf, 16); } } vui_ptr->overscan_info_present_flag = get_1bit(buf); if(vui_ptr->overscan_info_present_flag) { vui_ptr->overscan_appropriate_flag = get_1bit(buf); } vui_ptr->video_signal_type_present_flag = get_1bit(buf); if(vui_ptr->video_signal_type_present_flag) { vui_ptr->video_format = get_bits(buf, 3); vui_ptr->video_full_range_flag = get_1bit(buf); vui_ptr->colour_description_present_flag = get_1bit(buf); if(vui_ptr->colour_description_present_flag) { vui_ptr->colour_primaries = get_bits(buf, 8); vui_ptr->transfer_characteristics = get_bits(buf, 8); vui_ptr->matrix_coefficients = get_bits(buf, 8); } } vui_ptr->chroma_loc_info_present_flag = get_1bit(buf); if(vui_ptr->chroma_loc_info_present_flag) { vui_ptr->chroma_sample_loc_type_top_field = parse_ue(buf); vui_ptr->chroma_sample_loc_type_bottom_field = parse_ue(buf); } vui_ptr->timing_info_present_flag = get_1bit(buf); if(vui_ptr->timing_info_present_flag) { vui_ptr->num_units_in_tick = get_bits(buf, 32); vui_ptr->time_scale = get_bits(buf, 32); vui_ptr->fixed_frame_rate_flag = get_1bit(buf); } vui_ptr->nal_hrd_parameters_present_flag = get_1bit(buf); if(vui_ptr->nal_hrd_parameters_present_flag) { vui_ptr->cpb_cnt_minus1 = parse_ue(buf); vui_ptr->bit_rate_scale = get_bits(buf, 4); vui_ptr->cpb_size_scale = get_bits(buf, 4); for(SchedSelIdx=0; SchedSelIdx<=vui_ptr->cpb_cnt_minus1; SchedSelIdx++) { vui_ptr->bit_rate_value_minus1[SchedSelIdx] = parse_ue(buf); vui_ptr->cpb_size_value_minus1[SchedSelIdx] = parse_ue(buf); vui_ptr->cbr_flag[SchedSelIdx] = get_1bit(buf); } vui_ptr->initial_cpb_removal_delay_length_minus1 = get_bits(buf, 5); vui_ptr->cpb_removal_delay_length_minus1 = get_bits(buf, 5); vui_ptr->dpb_output_delay_length_minus1 = get_bits(buf, 5); vui_ptr->time_offset_length = get_bits(buf, 5); } vui_ptr->vcl_hrd_parameters_present_flag = get_1bit(buf); if(vui_ptr->vcl_hrd_parameters_present_flag) { vui_ptr->cpb_cnt_minus1 = parse_ue(buf); vui_ptr->bit_rate_scale = get_bits(buf, 4); vui_ptr->cpb_size_scale = get_bits(buf, 4); for(SchedSelIdx=0; SchedSelIdx<=vui_ptr->cpb_cnt_minus1; SchedSelIdx++) { vui_ptr->bit_rate_value_minus1[SchedSelIdx] = parse_ue(buf); vui_ptr->cpb_size_value_minus1[SchedSelIdx] = parse_ue(buf); vui_ptr->cbr_flag[SchedSelIdx] = get_1bit(buf); } vui_ptr->initial_cpb_removal_delay_length_minus1 = get_bits(buf, 5); vui_ptr->cpb_removal_delay_length_minus1 = get_bits(buf, 5); vui_ptr->dpb_output_delay_length_minus1 = get_bits(buf, 5); vui_ptr->time_offset_length = get_bits(buf, 5); } if(vui_ptr->nal_hrd_parameters_present_flag \ || vui_ptr->vcl_hrd_parameters_present_flag) { vui_ptr->low_delay_hrd_flag = get_1bit(buf); } vui_ptr->pic_struct_present_flag = get_1bit(buf); vui_ptr->bitstream_restriction_flag = get_1bit(buf); if(vui_ptr->bitstream_restriction_flag) { vui_ptr->motion_vectors_over_pic_boundaries_flag = get_1bit(buf); vui_ptr->max_bytes_per_pic_denom = parse_ue(buf); vui_ptr->max_bits_per_mb_denom = parse_ue(buf); vui_ptr->log2_max_mv_length_horizontal= parse_ue(buf); vui_ptr->log2_max_mv_length_vertical = parse_ue(buf); vui_ptr->num_reorder_frames = parse_ue(buf); vui_ptr->max_dec_frame_buffering = parse_ue(buf); } exit: return ret; } /** * @brief Function sps_info_print() µ÷ÊÔÐÅÏ¢´òÓ¡ * @param[in] sps_ptr spsÐÅÏ¢½á¹¹ÌåÖ¸Õë * @retval * @pre * @post */ #ifdef SPS_PPS_DEBUG /*SPS ÐÅÏ¢´òÓ¡£¬µ÷ÊÔʹÓÃ*/ static void sps_info_print(SPS* sps_ptr) { if(NULL != sps_ptr) { RPT(RPT_DBG, "profile_idc: %d", sps_ptr->profile_idc); RPT(RPT_DBG, "constraint_set0_flag: %d", sps_ptr->constraint_set0_flag); RPT(RPT_DBG, "constraint_set1_flag: %d", sps_ptr->constraint_set1_flag); RPT(RPT_DBG, "constraint_set2_flag: %d", sps_ptr->constraint_set2_flag); RPT(RPT_DBG, "constraint_set3_flag: %d", sps_ptr->constraint_set3_flag); RPT(RPT_DBG, "reserved_zero_4bits: %d", sps_ptr->reserved_zero_4bits); RPT(RPT_DBG, "level_idc: %d", sps_ptr->level_idc); RPT(RPT_DBG, "seq_parameter_set_id: %d", sps_ptr->seq_parameter_set_id); RPT(RPT_DBG, "chroma_format_idc: %d", sps_ptr->chroma_format_idc); RPT(RPT_DBG, "separate_colour_plane_flag: %d", sps_ptr->separate_colour_plane_flag); RPT(RPT_DBG, "bit_depth_luma_minus8: %d", sps_ptr->bit_depth_luma_minus8); RPT(RPT_DBG, "bit_depth_chroma_minus8: %d", sps_ptr->bit_depth_chroma_minus8); RPT(RPT_DBG, "qpprime_y_zero_transform_bypass_flag: %d", sps_ptr->qpprime_y_zero_transform_bypass_flag); RPT(RPT_DBG, "seq_scaling_matrix_present_flag: %d", sps_ptr->seq_scaling_matrix_present_flag); //RPT(RPT_INF, "seq_scaling_list_present_flag:%d", sps_ptr->seq_scaling_list_present_flag); RPT(RPT_DBG, "log2_max_frame_num_minus4: %d", sps_ptr->log2_max_frame_num_minus4); RPT(RPT_DBG, "pic_order_cnt_type: %d", sps_ptr->pic_order_cnt_type); RPT(RPT_DBG, "num_ref_frames: %d", sps_ptr->num_ref_frames); RPT(RPT_DBG, "gaps_in_frame_num_value_allowed_flag: %d", sps_ptr->gaps_in_frame_num_value_allowed_flag); RPT(RPT_DBG, "pic_width_in_mbs_minus1: %d", sps_ptr->pic_width_in_mbs_minus1); RPT(RPT_DBG, "pic_height_in_map_units_minus1: %d", sps_ptr->pic_height_in_map_units_minus1); RPT(RPT_DBG, "frame_mbs_only_flag: %d", sps_ptr->frame_mbs_only_flag); RPT(RPT_DBG, "mb_adaptive_frame_field_flag: %d", sps_ptr->mb_adaptive_frame_field_flag); RPT(RPT_DBG, "direct_8x8_inference_flag: %d", sps_ptr->direct_8x8_inference_flag); RPT(RPT_DBG, "frame_cropping_flag: %d", sps_ptr->frame_cropping_flag); RPT(RPT_DBG, "frame_crop_left_offset: %d", sps_ptr->frame_crop_left_offset); RPT(RPT_DBG, "frame_crop_right_offset: %d", sps_ptr->frame_crop_right_offset); RPT(RPT_DBG, "frame_crop_top_offset: %d", sps_ptr->frame_crop_top_offset); RPT(RPT_DBG, "frame_crop_bottom_offset: %d", sps_ptr->frame_crop_bottom_offset); RPT(RPT_DBG, "vui_parameters_present_flag: %d", sps_ptr->vui_parameters_present_flag); if(sps_ptr->vui_parameters_present_flag) { RPT(RPT_DBG, "aspect_ratio_info_present_flag: %d", sps_ptr->vui_parameters.aspect_ratio_info_present_flag); RPT(RPT_DBG, "aspect_ratio_idc: %d", sps_ptr->vui_parameters.aspect_ratio_idc); RPT(RPT_DBG, "sar_width: %d", sps_ptr->vui_parameters.sar_width); RPT(RPT_DBG, "sar_height: %d", sps_ptr->vui_parameters.sar_height); RPT(RPT_DBG, "overscan_info_present_flag: %d", sps_ptr->vui_parameters.overscan_info_present_flag); RPT(RPT_DBG, "overscan_info_appropriate_flag: %d", sps_ptr->vui_parameters.overscan_appropriate_flag); RPT(RPT_DBG, "video_signal_type_present_flag: %d", sps_ptr->vui_parameters.video_signal_type_present_flag); RPT(RPT_DBG, "video_format: %d", sps_ptr->vui_parameters.video_format); RPT(RPT_DBG, "video_full_range_flag: %d", sps_ptr->vui_parameters.video_full_range_flag); RPT(RPT_DBG, "colour_description_present_flag: %d", sps_ptr->vui_parameters.colour_description_present_flag); RPT(RPT_DBG, "colour_primaries: %d", sps_ptr->vui_parameters.colour_primaries); RPT(RPT_DBG, "transfer_characteristics: %d", sps_ptr->vui_parameters.transfer_characteristics); RPT(RPT_DBG, "matrix_coefficients: %d", sps_ptr->vui_parameters.matrix_coefficients); RPT(RPT_DBG, "chroma_loc_info_present_flag: %d", sps_ptr->vui_parameters.chroma_loc_info_present_flag); RPT(RPT_DBG, "chroma_sample_loc_type_top_field: %d", sps_ptr->vui_parameters.chroma_sample_loc_type_top_field); RPT(RPT_DBG, "chroma_sample_loc_type_bottom_field: %d", sps_ptr->vui_parameters.chroma_sample_loc_type_bottom_field); RPT(RPT_DBG, "timing_info_present_flag: %d", sps_ptr->vui_parameters.timing_info_present_flag); RPT(RPT_DBG, "num_units_in_tick: %d", sps_ptr->vui_parameters.num_units_in_tick); RPT(RPT_DBG, "time_scale: %d", sps_ptr->vui_parameters.time_scale); RPT(RPT_DBG, "fixed_frame_rate_flag: %d", sps_ptr->vui_parameters.fixed_frame_rate_flag); RPT(RPT_DBG, "nal_hrd_parameters_present_flag: %d", sps_ptr->vui_parameters.nal_hrd_parameters_present_flag); RPT(RPT_DBG, "cpb_cnt_minus1: %d", sps_ptr->vui_parameters.cpb_cnt_minus1); RPT(RPT_DBG, "bit_rate_scale: %d", sps_ptr->vui_parameters.bit_rate_scale); RPT(RPT_DBG, "cpb_size_scale: %d", sps_ptr->vui_parameters.cpb_size_scale); RPT(RPT_DBG, "initial_cpb_removal_delay_length_minus1: %d", sps_ptr->vui_parameters.initial_cpb_removal_delay_length_minus1); RPT(RPT_DBG, "cpb_removal_delay_length_minus1: %d", sps_ptr->vui_parameters.cpb_removal_delay_length_minus1); RPT(RPT_DBG, "dpb_output_delay_length_minus1: %d", sps_ptr->vui_parameters.dpb_output_delay_length_minus1); RPT(RPT_DBG, "time_offset_length: %d", sps_ptr->vui_parameters.time_offset_length); RPT(RPT_DBG, "vcl_hrd_parameters_present_flag: %d", sps_ptr->vui_parameters.vcl_hrd_parameters_present_flag); RPT(RPT_DBG, "low_delay_hrd_flag: %d", sps_ptr->vui_parameters.low_delay_hrd_flag); RPT(RPT_DBG, "pic_struct_present_flag: %d", sps_ptr->vui_parameters.pic_struct_present_flag); RPT(RPT_DBG, "bitstream_restriction_flag: %d", sps_ptr->vui_parameters.bitstream_restriction_flag); RPT(RPT_DBG, "motion_vectors_over_pic_boundaries_flag: %d", sps_ptr->vui_parameters.motion_vectors_over_pic_boundaries_flag); RPT(RPT_DBG, "max_bytes_per_pic_denom: %d", sps_ptr->vui_parameters.max_bytes_per_pic_denom); RPT(RPT_DBG, "max_bits_per_mb_denom: %d", sps_ptr->vui_parameters.max_bits_per_mb_denom); RPT(RPT_DBG, "log2_max_mv_length_horizontal: %d", sps_ptr->vui_parameters.log2_max_mv_length_horizontal); RPT(RPT_DBG, "log2_max_mv_length_vertical: %d", sps_ptr->vui_parameters.log2_max_mv_length_vertical); RPT(RPT_DBG, "num_reorder_frames: %d", sps_ptr->vui_parameters.num_reorder_frames); RPT(RPT_DBG, "max_dec_frame_buffering: %d", sps_ptr->vui_parameters.max_dec_frame_buffering); } } } #endif int h265dec_seq_parameter_set(void *buf_ptr, int* width,int* height) { int ret = 0; //int profile_idc = 0; unsigned i; void *buf = NULL; unsigned sps_video_parameter_set_id = 0; unsigned sps_max_sub_layers_minus1 = 0; unsigned sps_temporal_id_nesting_flag = 0; unsigned sps_seq_parameter_set_id = 0; unsigned chroma_format_idc = 0; unsigned pic_width_in_luma_samples = 0; unsigned pic_height_in_luma_samples = 0; bool sub_layer_profile_present_flag[7], sub_layer_level_present_flag[7]; if(NULL == buf_ptr) { RPT(RPT_ERR,"ERR null pointer\n"); ret = -1; goto exit; } buf = de_emulation_prevention(buf_ptr); if(NULL == buf) { RPT(RPT_ERR,"ERR null pointer\n"); ret = -1; goto exit; } sps_video_parameter_set_id = get_bits(buf, 4);//sps_video_parameter_set_id sps_max_sub_layers_minus1 = get_bits(buf, 3);//sps_max_sub_layers_minus1 sps_temporal_id_nesting_flag = get_1bit(buf);//sps_temporal_id_nesting_flag get_bits(buf,32); get_bits(buf,32); get_bits(buf,32); for (i = 0; i < sps_max_sub_layers_minus1; ++i) { sub_layer_profile_present_flag[i] = get_1bit(buf); sub_layer_level_present_flag[i] = get_1bit(buf); } if (sps_max_sub_layers_minus1 > 0) { get_bits(buf,2*(8-sps_max_sub_layers_minus1)); // reserved_zero_2bits } for (i = 0; i < sps_max_sub_layers_minus1; ++i) { if (sub_layer_profile_present_flag[i]) { get_bits(buf,32); get_bits(buf,32); get_bits(buf,24); } if (sub_layer_level_present_flag[i]) { get_bits(buf,8); // sub_layer_level_idc[i] } } sps_seq_parameter_set_id = parse_ue(buf); // sps_seq_parameter_set_id chroma_format_idc = parse_ue(buf); if (chroma_format_idc == 3) get_1bit(buf); // separate_colour_plane_flag pic_width_in_luma_samples = parse_ue(buf); pic_height_in_luma_samples = parse_ue(buf); *width = pic_width_in_luma_samples; *height = pic_height_in_luma_samples; exit: get_bit_context_free(buf); return ret; } /** * @brief Function h264dec_seq_parameter_set() h264 SPS infomation ½âÎö * @param[in] buf buf ptr, Ðèͬ²½00 00 00 01 X7ºó´«Èë * @param[in] sps_ptr spsÖ¸Õ룬±£´æSPSÐÅÏ¢ * @retval 0: success, -1 : failure * @pre * @post */ int h264dec_seq_parameter_set(void *buf_ptr, SPS *sps_ptr) { SPS *sps = sps_ptr; int ret = 0; int profile_idc = 0; int i,j; void *buf = NULL; if(NULL == buf_ptr || NULL == sps) { RPT(RPT_ERR,"ERR null pointer\n"); ret = -1; goto exit; } memset((void *)sps, 0, sizeof(SPS)); buf = de_emulation_prevention(buf_ptr); if(NULL == buf) { RPT(RPT_ERR,"ERR null pointer\n"); ret = -1; goto exit; } sps->profile_idc = get_bits(buf, 8); sps->constraint_set0_flag = get_1bit(buf); sps->constraint_set1_flag = get_1bit(buf); sps->constraint_set2_flag = get_1bit(buf); sps->constraint_set3_flag = get_1bit(buf); sps->reserved_zero_4bits = get_bits(buf, 4); sps->level_idc = get_bits(buf, 8); sps->seq_parameter_set_id = parse_ue(buf); profile_idc = sps->profile_idc; if( (profile_idc == 100) || (profile_idc == 110) || (profile_idc == 122) || (profile_idc == 244) || (profile_idc == 44) || (profile_idc == 83) || (profile_idc == 86) || (profile_idc == 118) ||\ (profile_idc == 128)) { sps->chroma_format_idc = parse_ue(buf); if(sps->chroma_format_idc == 3) { sps->separate_colour_plane_flag = get_1bit(buf); } sps->bit_depth_luma_minus8 = parse_ue(buf); sps->bit_depth_chroma_minus8 = parse_ue(buf); sps->qpprime_y_zero_transform_bypass_flag = get_1bit(buf); sps->seq_scaling_matrix_present_flag = get_1bit(buf); if(sps->seq_scaling_matrix_present_flag) { for(i = 0;i<8;i++) { if(get_1bit(buf)) { int last =8,next = 8,size = (i<6)?16:64; for(j = 0;jchroma_format_idc != 3)?8:12); i++) //{ // sps->seq_scaling_list_present_flag[i] = get_1bit(buf); // if(sps->seq_scaling_list_present_flag[i]) // { // if(i<6) // { // for(j=0; j<16; j++) // { // last_scale = 8; // next_scale = 8; // if(next_scale != 0) // { // delta_scale = parse_se(buf); // next_scale = (last_scale + delta_scale + 256)%256; // sps->UseDefaultScalingMatrix4x4Flag[i] = ((j == 0) && (next_scale == 0)); // } // sps->ScalingList4x4[i][j] = (next_scale == 0)?last_scale:next_scale; // last_scale = sps->ScalingList4x4[i][j]; // } // } // else // { // int ii = i-6; // next_scale = 8; // last_scale = 8; // for(j=0; j<64; j++) // { // if(next_scale != 0) // { // delta_scale = parse_se(buf); // next_scale = (last_scale + delta_scale + 256)%256; // sps->UseDefaultScalingMatrix8x8Flag[ii] = ((j == 0) && (next_scale == 0)); // } // sps->ScalingList8x8[ii][j] = (next_scale == 0)?last_scale:next_scale; // last_scale = sps->ScalingList8x8[ii][j]; // } // } // } //} } } sps->log2_max_frame_num_minus4 = parse_ue(buf); sps->pic_order_cnt_type = parse_ue(buf); if(sps->pic_order_cnt_type == 0) { sps->log2_max_pic_order_cnt_lsb_minus4 = parse_ue(buf); } else if(sps->pic_order_cnt_type == 1) { sps->delta_pic_order_always_zero_flag = get_1bit(buf); sps->offset_for_non_ref_pic = parse_se(buf); sps->offset_for_top_to_bottom_field = parse_se(buf); sps->num_ref_frames_in_pic_order_cnt_cycle = parse_ue(buf); for(i=0; inum_ref_frames_in_pic_order_cnt_cycle; i++) { sps->offset_for_ref_frame_array[i] = parse_se(buf); } } sps->num_ref_frames = parse_ue(buf); sps->gaps_in_frame_num_value_allowed_flag = get_1bit(buf); sps->pic_width_in_mbs_minus1 = parse_ue(buf); sps->pic_height_in_map_units_minus1 = parse_ue(buf); sps->frame_mbs_only_flag = get_1bit(buf); if(!sps->frame_mbs_only_flag) { sps->mb_adaptive_frame_field_flag = get_1bit(buf); } sps->direct_8x8_inference_flag = get_1bit(buf); sps->frame_cropping_flag = get_1bit(buf); if(sps->frame_cropping_flag) { sps->frame_crop_left_offset = parse_ue(buf); sps->frame_crop_right_offset = parse_ue(buf); sps->frame_crop_top_offset = parse_ue(buf); sps->frame_crop_bottom_offset = parse_ue(buf); } sps->vui_parameters_present_flag = get_1bit(buf); if(sps->vui_parameters_present_flag) { vui_parameters_set(buf, &sps->vui_parameters); } #ifdef SPS_PPS_DEBUG sps_info_print(sps); #endif exit: get_bit_context_free(buf); return ret; } /** * @brief Function more_rbsp_data() ¼ÆËãpps´®×îºóÒ»¸öΪ1µÄ±ÈÌØÎ»¼°Æäºó¶¼ÊDZÈÌØ0µÄ¸öÊý * @param[in] buf get_bit_context structure * @retval * @pre * @post * @note Õâ¶Î´úÂëÀ´×ÔÍøÓѵİïÖú£¬²¢Ã»ÓÐÑéÖ¤£¬Ê¹ÓÃʱÐè×¢Òâ */ static int more_rbsp_data(void *buf) { get_bit_context *ptr = (get_bit_context *)buf; get_bit_context tmp; if(NULL == buf) { RPT(RPT_ERR, "NULL pointer, err"); return -1; } memset(&tmp, 0, sizeof(get_bit_context)); memcpy(&tmp, ptr, sizeof(get_bit_context)); for(tmp.bit_pos = ptr->total_bit - 1;tmp.bit_pos > ptr->bit_pos;tmp.bit_pos -= 2) { if(get_1bit(&tmp)) { break; } } return tmp.bit_pos == ptr->bit_pos? 0:1; } /** * @brief Function h264dec_picture_parameter_set() h264 PPS infomation ½âÎö * @param[in] buf buf ptr, Ðèͬ²½00 00 00 01 X8ºó´«Èë * @param[in] pps_ptr ppsÖ¸Õ룬±£´æppsÐÅÏ¢ * @retval 0: success, -1 : failure * @pre * @post */ int h264dec_picture_parameter_set(void *buf_ptr, PPS *pps_ptr) { PPS *pps = pps_ptr; int ret = 0; void *buf = NULL; int iGroup = 0; int i,j,last_scale, next_scale, delta_scale; if(NULL == buf_ptr || NULL == pps_ptr) { RPT(RPT_ERR, "NULL pointer\n"); ret = -1; goto exit; } memset((void *)pps, 0, sizeof(PPS)); buf = de_emulation_prevention(buf_ptr); if(NULL == buf) { RPT(RPT_ERR,"ERR null pointer\n"); ret = -1; goto exit; } pps->pic_parameter_set_id = parse_ue(buf); pps->seq_parameter_set_id = parse_ue(buf); pps->entropy_coding_mode_flag = get_1bit(buf); pps->pic_order_present_flag = get_1bit(buf); pps->num_slice_groups_minus1 = parse_ue(buf); if(pps->num_slice_groups_minus1 > 0) { pps->slice_group_map_type = parse_ue(buf); if(pps->slice_group_map_type == 0) { for(iGroup=0; iGroup<=pps->num_slice_groups_minus1; iGroup++) { pps->run_length_minus1[iGroup] = parse_ue(buf); } } else if(pps->slice_group_map_type == 2) { for(iGroup=0; iGroup<=pps->num_slice_groups_minus1; iGroup++) { pps->top_left[iGroup] = parse_ue(buf); pps->bottom_right[iGroup] = parse_ue(buf); } } else if(pps->slice_group_map_type == 3 \ ||pps->slice_group_map_type == 4\ ||pps->slice_group_map_type == 5) { pps->slice_group_change_direction_flag = get_1bit(buf); pps->slice_group_change_rate_minus1 = parse_ue(buf); } else if(pps->slice_group_map_type == 6) { pps->pic_size_in_map_units_minus1 = parse_ue(buf); for(i=0; ipic_size_in_map_units_minus1; i++) { /*ÕâµØ·½¿ÉÄÜÓÐÎÊÌ⣬¶Ôu(v)Àí½âÆ«²î*/ pps->slice_group_id[i] = get_bits(buf, pps->pic_size_in_map_units_minus1); } } } pps->num_ref_idx_10_active_minus1 = parse_ue(buf); pps->num_ref_idx_11_active_minus1 = parse_ue(buf); pps->weighted_pred_flag = get_1bit(buf); pps->weighted_bipred_idc = get_bits(buf, 2); pps->pic_init_qp_minus26 = parse_se(buf); /*relative26*/ pps->pic_init_qs_minus26 = parse_se(buf); /*relative26*/ pps->chroma_qp_index_offset = parse_se(buf); pps->deblocking_filter_control_present_flag = get_1bit(buf); pps->constrained_intra_pred_flag = get_1bit(buf); pps->redundant_pic_cnt_present_flag = get_1bit(buf); if(more_rbsp_data(buf)) { pps->transform_8x8_mode_flag = get_1bit(buf); pps->pic_scaling_matrix_present_flag = get_1bit(buf); if(pps->pic_scaling_matrix_present_flag) { for(i=0; i<6+2*pps->transform_8x8_mode_flag; i++) { pps->pic_scaling_list_present_flag[i] = get_1bit(buf); if(pps->pic_scaling_list_present_flag[i]) { if(i<6) { for(j=0; j<16; j++) { next_scale = 8; last_scale = 8; if(next_scale != 0) { delta_scale = parse_se(buf); next_scale = (last_scale + delta_scale + 256)%256; pps->UseDefaultScalingMatrix4x4Flag[i] = ((j == 0) && (next_scale == 0)); } pps->ScalingList4x4[i][j] = (next_scale == 0)?last_scale:next_scale; last_scale = pps->ScalingList4x4[i][j]; } } else { int ii = i-6; next_scale = 8; last_scale = 8; for(j=0; j<64; j++) { if(next_scale != 0) { delta_scale = parse_se(buf); next_scale = (last_scale + delta_scale + 256)%256; pps->UseDefaultScalingMatrix8x8Flag[ii] = ((j == 0) && (next_scale == 0)); } pps->ScalingList8x8[ii][j] = (next_scale == 0)?last_scale:next_scale; last_scale = pps->ScalingList8x8[ii][j]; } } } } pps->second_chroma_qp_index_offset = parse_se(buf); } } exit: get_bit_context_free(buf); return ret; } // calculation width height and framerate int h264_get_width(SPS *sps_ptr) { return (sps_ptr->pic_width_in_mbs_minus1 + 1) * 16; } int h264_get_height(SPS *sps_ptr) { return (sps_ptr->pic_height_in_map_units_minus1 + 1) * 16 * (2 - sps_ptr->frame_mbs_only_flag); } int h264_get_format(SPS *sps_ptr) { return sps_ptr->frame_mbs_only_flag; } /* 1 - 23.98 2 - 24 3 - 25 4 - 29.97 5 - 30 6 - 50 7 - 59.94 8 - 60 9 - 6 10 - 8 11 - 12 12 - 15 13 - 10. */ int h264_get_framerate(float *framerate,SPS *sps_ptr) { int fr; int fr_int; if(sps_ptr->vui_parameters.timing_info_present_flag) { if(sps_ptr->vui_parameters.num_units_in_tick == 0 || sps_ptr->vui_parameters.time_scale == 0) { *framerate = 25.0; return 3; } if(sps_ptr->frame_mbs_only_flag == 0 && sps_ptr->vui_parameters.fixed_frame_rate_flag == 1) { *framerate = (float)sps_ptr->vui_parameters.time_scale / (float)sps_ptr->vui_parameters.num_units_in_tick/2.0; //fr_int = sps_ptr->vui_parameters.time_scale / sps_ptr->vui_parameters.num_units_in_tick / 2; } else if(sps_ptr->frame_mbs_only_flag == 1) { *framerate = (float)sps_ptr->vui_parameters.time_scale / (float)sps_ptr->vui_parameters.num_units_in_tick/2.0; //fr_int = sps_ptr->vui_parameters.time_scale / sps_ptr->vui_parameters.num_units_in_tick / 2; } else { *framerate = (float)sps_ptr->vui_parameters.time_scale / (float)sps_ptr->vui_parameters.num_units_in_tick; //fr_int = sps_ptr->vui_parameters.time_scale / sps_ptr->vui_parameters.num_units_in_tick; } fr_int = sps_ptr->vui_parameters.time_scale / sps_ptr->vui_parameters.num_units_in_tick / 2; } else { *framerate = 25.0; return 3; } switch(fr_int) { case 23:// 23.98 fr = 1; break; case 24: fr = 2; break; case 25: fr = 3; break; case 29://29.97 fr = 4; break; case 30: fr = 5; break; case 50: fr = 6; break; case 59://59.94 fr = 7; break; case 60: fr = 8; break; case 6: fr = 10; break; case 8: fr = 11; break; case 12: fr = 12; break; case 15: fr = 13; break; case 10: fr = 14; break; default: fr = 0; break; } return fr; } // for mpeg-2 void memcpy_sps_data(uint8_t *dst,uint8_t *src,int len) { int tmp; for(tmp = 0; tmp < len; tmp++) { //printf("0x%02x ", src[tmp]); dst[(tmp/4)*4+(3 - (tmp % 4))] = src[tmp]; } } /*_*/ ////////////////////////////////////////////////////////// //H264 bool inline is_sps_header(slice_header_t* sps) { if(sps->start_code_prefix[0] == 0 && sps->start_code_prefix[1] == 0 && sps->start_code_prefix[2] == 0 && sps->start_code_prefix[3] == 1 && ((sps->start_code_prefix[4]&0x1f) == 7)) return true; return false; } bool inline is_pps_header(slice_header_t* pps) { if(pps->start_code_prefix[0] == 0 && pps->start_code_prefix[1] == 0 && pps->start_code_prefix[2] == 0 && pps->start_code_prefix[3] == 1 && ((pps->start_code_prefix[4]&0x1f) == 8)) return true; return false; } bool inline is_sei_header(slice_header_t* sei) { if(sei->start_code_prefix[0] == 0 && sei->start_code_prefix[1] == 0 && sei->start_code_prefix[2] == 0 && sei->start_code_prefix[3] == 1 && ((sei->start_code_prefix[4]&0x1f) == 6)) return true; return false; } bool inline is_IFrame_header(slice_header_t* IFrame) { if(IFrame->start_code_prefix[0] == 0 && IFrame->start_code_prefix[1] == 0 && IFrame->start_code_prefix[2] == 0 && IFrame->start_code_prefix[3] == 1 && ((IFrame->start_code_prefix[4]&0x1f) == 5)) { // 0x00 0x00 0x00 0x01 0x65 return true; } else if(IFrame->start_code_prefix[0] == 0 && IFrame->start_code_prefix[1] == 0 && IFrame->start_code_prefix[2] == 1 && ((IFrame->start_code_prefix[3]&0x1f) == 5)) { // 0x00 0x00 0x01 0x65 return true; } return false; } bool inline is_PFrame_header(slice_header_t* PFrame) { if(PFrame->start_code_prefix[0] == 0 && PFrame->start_code_prefix[1] == 0 && PFrame->start_code_prefix[2] == 0 && PFrame->start_code_prefix[3] == 1 && ((PFrame->start_code_prefix[4]&0x1f) == 1)) return true; return false; } void get_sps_pps_len(uint8_t *h264_data,int h264_len,int* sps_len,int* pps_len,int* Iframe_len) { int nPos_SPS = 0;//SPSÓαêλÖà int nPos_PPS = 0;//PPSÓαêλÖà int nPos_IFrame = 0;//¹Ø¼üÖ¡ÓαêλÖà int nPos = 0;//±éÀúÓαêλÖà int nSizeSPS,nSizePPS,nSizeIFrame = 0; slice_header_t* sps; slice_header_t* pps; slice_header_t* IFrame; sps = (slice_header_t*)(h264_data); if(is_sps_header(sps)) { for(; nPosstart_code_prefix[4] & 0x7E) >> 1; if(vps->start_code_prefix[0] == 0 && vps->start_code_prefix[1] == 0 && vps->start_code_prefix[2] == 0 && vps->start_code_prefix[3] == 1 && nal_type == 32) return true; return false; } bool inline is_hevc_sps_header(slice_header_t* sps) { int nal_type = 0; nal_type = (sps->start_code_prefix[4] & 0x7E) >> 1; if(sps->start_code_prefix[0] == 0 && sps->start_code_prefix[1] == 0 && sps->start_code_prefix[2] == 0 && sps->start_code_prefix[3] == 1 && nal_type == 33) return true; return false; } bool inline is_hevc_pps_header(slice_header_t* pps) { int nal_type = 0; nal_type = (pps->start_code_prefix[4] & 0x7E) >> 1; if(pps->start_code_prefix[0] == 0 && pps->start_code_prefix[1] == 0 && pps->start_code_prefix[2] == 0 && pps->start_code_prefix[3] == 1 && nal_type == 34) return true; return false; } bool inline is_hevc_IFrame_header(slice_header_t* Iframe) { int nal_type = 0; nal_type = (Iframe->start_code_prefix[4] & 0x7E) >> 1; if(Iframe->start_code_prefix[0] == 0 && Iframe->start_code_prefix[1] == 0 && Iframe->start_code_prefix[2] == 0 && Iframe->start_code_prefix[3] == 1 && nal_type == 19) return true; return false; } bool inline is_hevc_PFrame_header(slice_header_t* Pframe) { int nal_type = 0; nal_type = (Pframe->start_code_prefix[4] & 0x7E) >> 1; if(Pframe->start_code_prefix[0] == 0 && Pframe->start_code_prefix[1] == 0 && Pframe->start_code_prefix[2] == 0 && Pframe->start_code_prefix[3] == 1 && nal_type == 1) return true; return false; } bool inline is_hevc_SEI_header(slice_header_t* sei) { int nal_type = 0; nal_type = (sei->start_code_prefix[4] & 0x7E) >> 1; if(sei->start_code_prefix[0] == 0 && sei->start_code_prefix[1] == 0 && sei->start_code_prefix[2] == 0 && sei->start_code_prefix[3] == 1 && nal_type == 39) return true; return false; } void get_vps_sps_pps_len(uint8_t *h265_data,int h265_len,int* vps_len,int* sps_len,int* pps_len,int* Iframe_len) { int nPos_VPS = 0;//VPSÓαêλÖà int nPos_SPS = 0;//SPSÓαêλÖà int nPos_PPS = 0;//PPSÓαêλÖà int nPos_IFrame = 0;//¹Ø¼üÖ¡ÓαêλÖà int nPos = 0;//±éÀúÓαêλÖà int nSizeVPS,nSizeSPS,nSizePPS,nSizeIFrame = 0; slice_header_t* vps; slice_header_t* sps; slice_header_t* pps; slice_header_t* IFrame; vps = (slice_header_t*)(h265_data); if(is_hevc_vps_header(vps)) { for(; nPosstart_code_prefix[0] == 0 && VOL->start_code_prefix[1] == 0 && VOL->start_code_prefix[2] == 0x01 && VOL->start_code_prefix[3] == 0x20) return true; return false; } //MPEG2 bool is_sequence_header(mpeg_header_t* SH) { if((SH->start_code_prefix[0] == 0 && SH->start_code_prefix[1] == 0 && SH->start_code_prefix[2] == 0x01 && SH->start_code_prefix[3] == 0xB3)) return true; return false; } bool is_H264_IFrame_Data(uint8_t *h264_data,int h264_len) { int nPos = 0;//±éÀúÓαêλÖà slice_header_t* sps; slice_header_t* pps; slice_header_t* IFrame; sps = (slice_header_t*)(h264_data); if(is_sps_header(sps)) { for(; nPos