diff options
Diffstat (limited to 'decoder')
-rw-r--r-- | decoder/ihevcd_api.c | 5 | ||||
-rw-r--r-- | decoder/ihevcd_bitstream.c | 12 | ||||
-rw-r--r-- | decoder/ihevcd_decode.c | 38 | ||||
-rw-r--r-- | decoder/ihevcd_iquant_itrans_recon_ctb.c | 5 | ||||
-rw-r--r-- | decoder/ihevcd_nal.c | 10 | ||||
-rw-r--r-- | decoder/ihevcd_parse_headers.c | 781 | ||||
-rw-r--r-- | decoder/ihevcd_parse_headers.h | 7 | ||||
-rw-r--r-- | decoder/ihevcd_parse_slice_header.c | 13 | ||||
-rw-r--r-- | decoder/ihevcd_structs.h | 5 | ||||
-rwxr-xr-x | decoder/ihevcd_utils.c | 62 |
10 files changed, 917 insertions, 21 deletions
diff --git a/decoder/ihevcd_api.c b/decoder/ihevcd_api.c index 4a96ba4..8abef0f 100644 --- a/decoder/ihevcd_api.c +++ b/decoder/ihevcd_api.c @@ -1247,18 +1247,21 @@ WORD32 ihevcd_allocate_static_bufs(iv_obj_t **pps_codec_obj, size = MAX_VPS_CNT * sizeof(vps_t); pv_buf = pf_aligned_alloc(pv_mem_ctxt, 128, size); RETURN_IF((NULL == pv_buf), IV_FAIL); + memset(pv_buf, 0, size); ps_codec->ps_vps_base = pv_buf; ps_codec->s_parse.ps_vps_base = ps_codec->ps_vps_base; size = MAX_SPS_CNT * sizeof(sps_t); pv_buf = pf_aligned_alloc(pv_mem_ctxt, 128, size); RETURN_IF((NULL == pv_buf), IV_FAIL); + memset(pv_buf, 0, size); ps_codec->ps_sps_base = pv_buf; ps_codec->s_parse.ps_sps_base = ps_codec->ps_sps_base; size = MAX_PPS_CNT * sizeof(pps_t); pv_buf = pf_aligned_alloc(pv_mem_ctxt, 128, size); RETURN_IF((NULL == pv_buf), IV_FAIL); + memset(pv_buf, 0, size); ps_codec->ps_pps_base = pv_buf; ps_codec->s_parse.ps_pps_base = ps_codec->ps_pps_base; @@ -1311,6 +1314,7 @@ WORD32 ihevcd_allocate_static_bufs(iv_obj_t **pps_codec_obj, size = 3 * 16 * sizeof(UWORD8); pu1_buf = pf_aligned_alloc(pv_mem_ctxt, 128, size); RETURN_IF((NULL == pu1_buf), IV_FAIL); + memset(pu1_buf, 0, size); ps_codec->s_parse.pu1_luma_intra_pred_mode_left = pu1_buf; ps_codec->s_parse.pu1_luma_intra_pred_mode_top = pu1_buf + 16; @@ -1917,6 +1921,7 @@ WORD32 ihevcd_allocate_dynamic_bufs(codec_t *ps_codec) size = ihevcd_get_tu_data_size(wd * ht); pv_buf = ps_codec->pf_aligned_alloc(pv_mem_ctxt, 128, size); RETURN_IF((NULL == pv_buf), IV_FAIL); + memset(pv_buf, 0, size); ps_codec->pv_tu_data = pv_buf; { diff --git a/decoder/ihevcd_bitstream.c b/decoder/ihevcd_bitstream.c index be9addb..3b8d24f 100644 --- a/decoder/ihevcd_bitstream.c +++ b/decoder/ihevcd_bitstream.c @@ -414,8 +414,16 @@ UWORD32 ihevcd_bits_num_bits_remaining(bitstrm_t *ps_bitstrm) 3) + ps_bitstrm->u4_bit_ofst; u4_size_in_bits = (UWORD32)(ps_bitstrm->pu1_buf_max - - ps_bitstrm->pu1_buf_base); - return (u4_size_in_bits - u4_bits_consumed); + ps_bitstrm->pu1_buf_base) - 8; + u4_size_in_bits <<= 3; + if(u4_size_in_bits > u4_bits_consumed) + { + return (u4_size_in_bits - u4_bits_consumed); + } + else + { + return 0; + } } /** diff --git a/decoder/ihevcd_decode.c b/decoder/ihevcd_decode.c index c38a930..d2ea7a5 100644 --- a/decoder/ihevcd_decode.c +++ b/decoder/ihevcd_decode.c @@ -205,6 +205,18 @@ static void ihevcd_fill_outargs(codec_t *ps_codec, ps_dec_op->u4_output_present = 0; ps_dec_op->u4_progressive_frame_flag = 1; + if(ps_codec->i4_sps_done) + { + sps_t *ps_sps = (ps_codec->s_parse.ps_sps_base + ps_codec->i4_sps_id); + profile_tier_lvl_info_t *ps_ptl; + ps_ptl = &ps_sps->s_ptl; + if((0 == ps_ptl->s_ptl_gen.i1_general_progressive_source_flag) && + (1 == ps_ptl->s_ptl_gen.i1_general_interlaced_source_flag)) + { + ps_dec_op->u4_progressive_frame_flag = 0; + } + } + ps_dec_op->u4_is_ref_flag = 1; ps_dec_op->e_output_format = ps_codec->e_chroma_fmt; ps_dec_op->u4_is_ref_flag = 1; @@ -226,7 +238,30 @@ static void ihevcd_fill_outargs(codec_t *ps_codec, if(ps_codec->ps_disp_buf) { pic_buf_t *ps_disp_buf = ps_codec->ps_disp_buf; + sei_params_t *ps_sei = &ps_disp_buf->s_sei_params; + if(ps_sei->i1_sei_parameters_present_flag && + ps_sei->i1_pic_timing_params_present_flag) + { + UWORD32 u4_pic_struct; + u4_pic_struct = ps_sei->s_pic_timing_sei_params.u4_pic_struct; + switch(u4_pic_struct) + { + case 1: + ps_dec_op->e4_fld_type = IV_TOP_FLD; + ps_dec_op->u4_progressive_frame_flag = 0; + break; + case 2: + ps_dec_op->e4_fld_type = IV_BOT_FLD; + ps_dec_op->u4_progressive_frame_flag = 0; + break; + case 0: + default: + ps_dec_op->e4_fld_type = IV_FLD_TYPE_DEFAULT; + ps_dec_op->u4_progressive_frame_flag = 1; + break; + } + } ps_dec_op->u4_output_present = 1; ps_dec_op->u4_ts = ps_disp_buf->u4_ts; if((ps_codec->i4_flush_mode == 0) && (ps_codec->s_parse.i4_end_of_frame == 0)) @@ -641,8 +676,7 @@ WORD32 ihevcd_decode(iv_obj_t *ps_codec_obj, void *pv_api_ip, void *pv_api_op) continue; } - if((IVD_RES_CHANGED == ret) || - (IHEVCD_UNSUPPORTED_DIMENSIONS == ret)) + if(IVD_RES_CHANGED == ret) { break; } diff --git a/decoder/ihevcd_iquant_itrans_recon_ctb.c b/decoder/ihevcd_iquant_itrans_recon_ctb.c index 6009d09..a7cd167 100644 --- a/decoder/ihevcd_iquant_itrans_recon_ctb.c +++ b/decoder/ihevcd_iquant_itrans_recon_ctb.c @@ -943,7 +943,10 @@ WORD32 ihevcd_iquant_itrans_recon_ctb(process_ctxt_t *ps_proc) /***************************************************************/ if(intra_flag) /* Intra */ { - UWORD8 au1_ref_sub_out[(MAX_TU_SIZE * 2 * 2) + 4]; + /* While (MAX_TU_SIZE * 2 * 2) + 1 is the actaul size needed, + au1_ref_sub_out size is kept as multiple of 8, + so that SIMD functions can load 64 bits */ + UWORD8 au1_ref_sub_out[(MAX_TU_SIZE * 2 * 2) + 8]; UWORD8 *pu1_top_left, *pu1_top, *pu1_left; WORD32 luma_pred_func_idx, chroma_pred_func_idx; diff --git a/decoder/ihevcd_nal.c b/decoder/ihevcd_nal.c index cc4a27f..d00050d 100644 --- a/decoder/ihevcd_nal.c +++ b/decoder/ihevcd_nal.c @@ -451,6 +451,16 @@ IHEVCD_ERROR_T ihevcd_nal_unit(codec_t *ps_codec) DEBUG_PRINT_NAL_INFO(ps_codec, s_nal.i1_nal_unit_type); break; + case NAL_PREFIX_SEI: + case NAL_SUFFIX_SEI: + if(IVD_DECODE_HEADER == ps_codec->i4_header_mode) + { + return IHEVCD_SLICE_IN_HEADER_MODE; + } + + ret = ihevcd_parse_sei(ps_codec, &s_nal); + break; + case NAL_EOS : ps_codec->i4_cra_as_first_pic = 1; break; diff --git a/decoder/ihevcd_parse_headers.c b/decoder/ihevcd_parse_headers.c index 427261c..6a02cbd 100644 --- a/decoder/ihevcd_parse_headers.c +++ b/decoder/ihevcd_parse_headers.c @@ -421,7 +421,6 @@ IHEVCD_ERROR_T ihevcd_short_term_ref_pic_set(bitstrm_t *ps_bitstrm, if(0 == ref_idc) { BITS_PARSE("use_delta_flag", value, ps_bitstrm, 1); - ps_stref_picset->ai1_used[i] = value; ref_idc = value << 1; } if((ref_idc == 1) || (ref_idc == 2)) @@ -669,22 +668,97 @@ static WORD32 ihevcd_parse_vui_parameters(bitstrm_t *ps_bitstrm, WORD32 sps_max_sub_layers_minus1) { WORD32 ret = (IHEVCD_ERROR_T)IHEVCD_SUCCESS; + UWORD16 u2_sar_width = 0; + UWORD16 u2_sar_height = 0; BITS_PARSE("aspect_ratio_info_present_flag", ps_vui->u1_aspect_ratio_info_present_flag, ps_bitstrm, 1); ps_vui->u1_aspect_ratio_idc = SAR_UNUSED; - ps_vui->u2_sar_width = 0; - ps_vui->u2_sar_height = 0; + u2_sar_width = 0; + u2_sar_height = 0; if(ps_vui->u1_aspect_ratio_info_present_flag) { BITS_PARSE("aspect_ratio_idc", ps_vui->u1_aspect_ratio_idc, ps_bitstrm, 8); - if(ps_vui->u1_aspect_ratio_idc == EXTENDED_SAR) + switch(ps_vui->u1_aspect_ratio_idc) { - BITS_PARSE("sar_width", ps_vui->u2_sar_width, ps_bitstrm, 16); - BITS_PARSE("sar_height", ps_vui->u2_sar_height, ps_bitstrm, 16); + case SAR_1_1: + u2_sar_width = 1; + u2_sar_height = 1; + break; + case SAR_12_11: + u2_sar_width = 12; + u2_sar_height = 11; + break; + case SAR_10_11: + u2_sar_width = 10; + u2_sar_height = 11; + break; + case SAR_16_11: + u2_sar_width = 16; + u2_sar_height = 11; + break; + case SAR_40_33: + u2_sar_width = 40; + u2_sar_height = 33; + break; + case SAR_24_11: + u2_sar_width = 24; + u2_sar_height = 11; + break; + case SAR_20_11: + u2_sar_width = 20; + u2_sar_height = 11; + break; + case SAR_32_11: + u2_sar_width = 32; + u2_sar_height = 11; + break; + case SAR_80_33: + u2_sar_width = 80; + u2_sar_height = 33; + break; + case SAR_18_11: + u2_sar_width = 18; + u2_sar_height = 11; + break; + case SAR_15_11: + u2_sar_width = 15; + u2_sar_height = 11; + break; + case SAR_64_33: + u2_sar_width = 64; + u2_sar_height = 33; + break; + case SAR_160_99: + u2_sar_width = 160; + u2_sar_height = 99; + break; + case SAR_4_3: + u2_sar_width = 4; + u2_sar_height = 3; + break; + case SAR_3_2: + u2_sar_width = 3; + u2_sar_height = 2; + break; + case SAR_2_1: + u2_sar_width = 2; + u2_sar_height = 1; + break; + case EXTENDED_SAR: + BITS_PARSE("sar_width", u2_sar_width, ps_bitstrm, 16); + BITS_PARSE("sar_height", u2_sar_height, ps_bitstrm, 16); + break; + default: + u2_sar_width = 0; + u2_sar_height = 0; + break; } } + ps_vui->u2_sar_width = u2_sar_width; + ps_vui->u2_sar_height = u2_sar_height; + BITS_PARSE("overscan_info_present_flag", ps_vui->u1_overscan_info_present_flag, ps_bitstrm, 1); ps_vui->u1_overscan_appropriate_flag = 0; if(ps_vui->u1_overscan_info_present_flag) @@ -831,13 +905,13 @@ static IHEVCD_ERROR_T ihevcd_parse_profile_tier_level_layer(bitstrm_t *ps_bitstr ps_ptl->i1_general_progressive_source_flag = value; BITS_PARSE("general_interlaced_source_flag", value, ps_bitstrm, 1); - ps_ptl->i1_general_progressive_source_flag = value; + ps_ptl->i1_general_interlaced_source_flag = value; BITS_PARSE("general_non_packed_constraint_flag", value, ps_bitstrm, 1); - ps_ptl->i1_general_progressive_source_flag = value; + ps_ptl->i1_general_non_packed_constraint_flag = value; BITS_PARSE("general_frame_only_constraint_flag", value, ps_bitstrm, 1); - ps_ptl->i1_general_progressive_source_flag = value; + ps_ptl->i1_frame_only_constraint_flag = value; BITS_PARSE("XXX_reserved_zero_44bits[0..15]", value, ps_bitstrm, 16); @@ -890,6 +964,10 @@ static IHEVCD_ERROR_T ihevcd_profile_tier_level(bitstrm_t *ps_bitstrm, if(profile_present) { ret = ihevcd_parse_profile_tier_level_layer(ps_bitstrm, &ps_ptl->s_ptl_gen); + if((IHEVCD_ERROR_T)IHEVCD_SUCCESS != ret) + { + return ret; + } } BITS_PARSE("general_level_idc", value, ps_bitstrm, 8); @@ -1504,7 +1582,7 @@ IHEVCD_ERROR_T ihevcd_parse_sps(codec_t *ps_codec) for(i = 0; i < ps_sps->i1_num_long_term_ref_pics_sps; i++) { BITS_PARSE("lt_ref_pic_poc_lsb_sps[ i ]", value, ps_bitstrm, ps_sps->i1_log2_max_pic_order_cnt_lsb); - ps_sps->ai1_lt_ref_pic_poc_lsb_sps[i] = value; + ps_sps->au2_lt_ref_pic_poc_lsb_sps[i] = value; BITS_PARSE("used_by_curr_pic_lt_sps_flag[ i ]", value, ps_bitstrm, 1); ps_sps->ai1_used_by_curr_pic_lt_sps_flag[i] = value; @@ -1576,6 +1654,13 @@ IHEVCD_ERROR_T ihevcd_parse_sps(codec_t *ps_codec) return (IHEVCD_ERROR_T)IVD_RES_CHANGED; } + if((ps_sps->i2_pic_width_in_luma_samples > MAX_WD) || + ((ps_sps->i2_pic_width_in_luma_samples * ps_sps->i2_pic_height_in_luma_samples) > + (MAX_WD * MAX_HT))) + { + return (IHEVCD_ERROR_T)IVD_STREAM_WIDTH_HEIGHT_NOT_SUPPORTED; + } + /* Update display width and display height */ { WORD32 disp_wd, disp_ht; @@ -2056,7 +2141,633 @@ void ihevcd_copy_pps(codec_t *ps_codec, WORD32 pps_id, WORD32 pps_id_ref) } +IHEVCD_ERROR_T ihevcd_parse_buffering_period_sei(codec_t *ps_codec, + sps_t *ps_sps) +{ + parse_ctxt_t *ps_parse = &ps_codec->s_parse; + bitstrm_t *ps_bitstrm = &ps_parse->s_bitstrm; + UWORD32 value; + vui_t *ps_vui; + buf_period_sei_params_t *ps_buf_period_sei_params; + UWORD32 i; + hrd_params_t *ps_vui_hdr; + UWORD32 u4_cpb_cnt; + + ps_vui = &ps_sps->s_vui_parameters; + ps_vui_hdr = &ps_vui->s_vui_hrd_parameters; + + ps_buf_period_sei_params = &ps_parse->s_sei_params.s_buf_period_sei_params; + + ps_parse->s_sei_params.i1_buf_period_params_present_flag = 1; + + UEV_PARSE("bp_seq_parameter_set_id", value, ps_bitstrm); + ps_buf_period_sei_params->u1_bp_seq_parameter_set_id = value; + + if(!ps_vui_hdr->u1_sub_pic_cpb_params_present_flag) + { + BITS_PARSE("irap_cpb_params_present_flag", value, ps_bitstrm, 1); + ps_buf_period_sei_params->u1_rap_cpb_params_present_flag = value; + } + + if(ps_buf_period_sei_params->u1_rap_cpb_params_present_flag) + { + BITS_PARSE("cpb_delay_offset", + value, + ps_bitstrm, + (ps_vui_hdr->u1_au_cpb_removal_delay_length_minus1 + + 1)); + ps_buf_period_sei_params->u4_cpb_delay_offset = value; + + BITS_PARSE("dpb_delay_offset", + value, + ps_bitstrm, + (ps_vui_hdr->u1_dpb_output_delay_length_minus1 + + 1)); + ps_buf_period_sei_params->u4_dpb_delay_offset = value; + } + else + { + ps_buf_period_sei_params->u4_cpb_delay_offset = 0; + ps_buf_period_sei_params->u4_dpb_delay_offset = 0; + } + + BITS_PARSE("concatenation_flag", value, ps_bitstrm, 1); + ps_buf_period_sei_params->u1_concatenation_flag = value; + + BITS_PARSE("au_cpb_removal_delay_delta_minus1", + value, + ps_bitstrm, + (ps_vui_hdr->u1_au_cpb_removal_delay_length_minus1 + + 1)); + ps_buf_period_sei_params->u4_au_cpb_removal_delay_delta_minus1 = value; + + if(ps_vui_hdr->u1_nal_hrd_parameters_present_flag) + { + u4_cpb_cnt = ps_vui_hdr->au1_cpb_cnt_minus1[0]; + + for(i = 0; i <= u4_cpb_cnt; i++) + { + BITS_PARSE("nal_initial_cpb_removal_delay[i]", + value, + ps_bitstrm, + (ps_vui_hdr->u1_initial_cpb_removal_delay_length_minus1 + + 1)); + ps_buf_period_sei_params->au4_nal_initial_cpb_removal_delay[i] = + value; + + BITS_PARSE("nal_initial_cpb_removal_delay_offset", + value, + ps_bitstrm, + (ps_vui_hdr->u1_initial_cpb_removal_delay_length_minus1 + + 1)); + ps_buf_period_sei_params->au4_nal_initial_cpb_removal_delay_offset[i] = + value; + + if(ps_vui_hdr->u1_sub_pic_cpb_params_present_flag + || ps_buf_period_sei_params->u1_rap_cpb_params_present_flag) + { + BITS_PARSE("nal_initial_alt_cpb_removal_delay[i]", + value, + ps_bitstrm, + (ps_vui_hdr->u1_initial_cpb_removal_delay_length_minus1 + + 1)); + ps_buf_period_sei_params->au4_nal_initial_alt_cpb_removal_delay[i] = + value; + + BITS_PARSE("nal_initial_alt_cpb_removal_delay_offset", + value, + ps_bitstrm, + (ps_vui_hdr->u1_initial_cpb_removal_delay_length_minus1 + + 1)); + ps_buf_period_sei_params->au4_nal_initial_alt_cpb_removal_delay_offset[i] = + value; + } + } + } + + if(ps_vui_hdr->u1_vcl_hrd_parameters_present_flag) + { + u4_cpb_cnt = ps_vui_hdr->au1_cpb_cnt_minus1[0]; + + for(i = 0; i <= u4_cpb_cnt; i++) + { + BITS_PARSE("vcl_initial_cpb_removal_delay[i]", + value, + ps_bitstrm, + (ps_vui_hdr->u1_initial_cpb_removal_delay_length_minus1 + + 1)); + ps_buf_period_sei_params->au4_vcl_initial_cpb_removal_delay[i] = + value; + + BITS_PARSE("vcl_initial_cpb_removal_delay_offset", + value, + ps_bitstrm, + (ps_vui_hdr->u1_initial_cpb_removal_delay_length_minus1 + + 1)); + ps_buf_period_sei_params->au4_vcl_initial_cpb_removal_delay_offset[i] = + value; + + if(ps_vui_hdr->u1_sub_pic_cpb_params_present_flag + || ps_buf_period_sei_params->u1_rap_cpb_params_present_flag) + { + BITS_PARSE("vcl_initial_alt_cpb_removal_delay[i]", + value, + ps_bitstrm, + (ps_vui_hdr->u1_initial_cpb_removal_delay_length_minus1 + + 1)); + ps_buf_period_sei_params->au4_vcl_initial_alt_cpb_removal_delay[i] = + value; + + BITS_PARSE("vcl_initial_alt_cpb_removal_delay_offset", + value, + ps_bitstrm, + (ps_vui_hdr->u1_initial_cpb_removal_delay_length_minus1 + + 1)); + ps_buf_period_sei_params->au4_vcl_initial_alt_cpb_removal_delay_offset[i] = + value; + } + } + } + + return (IHEVCD_ERROR_T)IHEVCD_SUCCESS; +} + +IHEVCD_ERROR_T ihevcd_parse_pic_timing_sei(codec_t *ps_codec, sps_t *ps_sps) +{ + parse_ctxt_t *ps_parse = &ps_codec->s_parse; + bitstrm_t *ps_bitstrm = &ps_parse->s_bitstrm; + UWORD32 value; + vui_t *ps_vui; + UWORD32 i; + hrd_params_t *ps_vui_hdr; + UWORD32 u4_cpb_dpb_delays_present_flag = 0; + pic_timing_sei_params_t *ps_pic_timing; + + ps_pic_timing = &ps_parse->s_sei_params.s_pic_timing_sei_params; + ps_vui = &ps_sps->s_vui_parameters; + ps_vui_hdr = &ps_vui->s_vui_hrd_parameters; + ps_parse->s_sei_params.i1_pic_timing_params_present_flag = 1; + if(ps_vui->u1_frame_field_info_present_flag) + { + BITS_PARSE("pic_struct", value, ps_bitstrm, 4); + ps_pic_timing->u4_pic_struct = value; + + BITS_PARSE("source_scan_type", value, ps_bitstrm, 2); + ps_pic_timing->u4_source_scan_type = value; + + BITS_PARSE("duplicate_flag", value, ps_bitstrm, 1); + ps_pic_timing->u1_duplicate_flag = value; + } + + if(ps_vui_hdr->u1_nal_hrd_parameters_present_flag + || ps_vui_hdr->u1_vcl_hrd_parameters_present_flag) + { + u4_cpb_dpb_delays_present_flag = 1; + } + else + { + u4_cpb_dpb_delays_present_flag = 0; + } + + if(u4_cpb_dpb_delays_present_flag) + { + BITS_PARSE("au_cpb_removal_delay_minus1", value, ps_bitstrm, + (ps_vui_hdr->u1_au_cpb_removal_delay_length_minus1 + 1)); + ps_pic_timing->u4_au_cpb_removal_delay_minus1 = value; + + BITS_PARSE("pic_dpb_output_delay", value, ps_bitstrm, + (ps_vui_hdr->u1_dpb_output_delay_length_minus1 + 1)); + ps_pic_timing->u4_pic_dpb_output_delay = value; + + if(ps_vui_hdr->u1_sub_pic_cpb_params_present_flag) + { + BITS_PARSE("pic_dpb_output_du_delay", value, ps_bitstrm, + (ps_vui_hdr->u1_dpb_output_delay_du_length_minus1 + 1)); + ps_pic_timing->u4_pic_dpb_output_du_delay = value; + } + + if(ps_vui_hdr->u1_sub_pic_cpb_params_present_flag + && ps_vui_hdr->u1_sub_pic_cpb_params_in_pic_timing_sei_flag) + { + UWORD32 num_units_minus1; + UWORD32 array_size; + + UEV_PARSE("num_decoding_units_minus1", value, ps_bitstrm); + ps_pic_timing->u4_num_decoding_units_minus1 = value; + + num_units_minus1 = ps_pic_timing->u4_num_decoding_units_minus1; + array_size = (sizeof(ps_pic_timing->au4_num_nalus_in_du_minus1) + / sizeof(ps_pic_timing->au4_num_nalus_in_du_minus1[0])); + num_units_minus1 = CLIP3(num_units_minus1, 0,(array_size - 1)); + ps_pic_timing->u4_num_decoding_units_minus1 = num_units_minus1; + + BITS_PARSE("du_common_cpb_removal_delay_flag", value, ps_bitstrm, 1); + ps_pic_timing->u1_du_common_cpb_removal_delay_flag = value; + + if(ps_pic_timing->u1_du_common_cpb_removal_delay_flag) + { + BITS_PARSE("du_common_cpb_removal_delay_increment_minus1", + value, + ps_bitstrm, + (ps_vui_hdr->u1_du_cpb_removal_delay_increment_length_minus1 + + 1)); + ps_pic_timing->u4_du_common_cpb_removal_delay_increment_minus1 = + value; + } + + for(i = 0; i <= ps_pic_timing->u4_num_decoding_units_minus1; i++) + { + UEV_PARSE("num_nalus_in_du_minus1", value, ps_bitstrm); + ps_pic_timing->au4_num_nalus_in_du_minus1[i] = value; + + if((!ps_pic_timing->u1_du_common_cpb_removal_delay_flag) + && (i < ps_pic_timing->u4_num_decoding_units_minus1)) + { + BITS_PARSE("du_common_cpb_removal_delay_increment_minus1", + value, + ps_bitstrm, + (ps_vui_hdr->u1_du_cpb_removal_delay_increment_length_minus1 + + 1)); + ps_pic_timing->au4_du_cpb_removal_delay_increment_minus1[i] = + value; + } + } + } + } + + return (IHEVCD_ERROR_T)IHEVCD_SUCCESS; +} + +IHEVCD_ERROR_T ihevcd_parse_time_code_sei(codec_t *ps_codec) +{ + parse_ctxt_t *ps_parse = &ps_codec->s_parse; + bitstrm_t *ps_bitstrm = &ps_parse->s_bitstrm; + UWORD32 value; + time_code_t *ps_time_code; + WORD32 i; + + ps_parse->s_sei_params.i1_time_code_present_flag = 1; + ps_time_code = &ps_parse->s_sei_params.s_time_code; + + BITS_PARSE("num_clock_ts", value, ps_bitstrm, 2); + ps_time_code->u1_num_clock_ts = value; + + for(i = 0; i < ps_time_code->u1_num_clock_ts; i++) + { + BITS_PARSE("clock_timestamp_flag[i]", value, ps_bitstrm, 1); + ps_time_code->au1_clock_timestamp_flag[i] = value; + + if(ps_time_code->au1_clock_timestamp_flag[i]) + { + BITS_PARSE("units_field_based_flag[i]", value, ps_bitstrm, 1); + ps_time_code->au1_units_field_based_flag[i] = value; + + BITS_PARSE("counting_type[i]", value, ps_bitstrm, 5); + ps_time_code->au1_counting_type[i] = value; + + BITS_PARSE("full_timestamp_flag[i]", value, ps_bitstrm, 1); + ps_time_code->au1_full_timestamp_flag[i] = value; + + BITS_PARSE("discontinuity_flag[i]", value, ps_bitstrm, 1); + ps_time_code->au1_discontinuity_flag[i] = value; + + BITS_PARSE("cnt_dropped_flag[i]", value, ps_bitstrm, 1); + ps_time_code->au1_cnt_dropped_flag[i] = value; + + BITS_PARSE("n_frames[i]", value, ps_bitstrm, 9); + ps_time_code->au2_n_frames[i] = value; + + if(ps_time_code->au1_full_timestamp_flag[i]) + { + BITS_PARSE("seconds_value[i]", value, ps_bitstrm, 6); + ps_time_code->au1_seconds_value[i] = value; + + BITS_PARSE("minutes_value[i]", value, ps_bitstrm, 6); + ps_time_code->au1_minutes_value[i] = value; + + BITS_PARSE("hours_value[i]", value, ps_bitstrm, 5); + ps_time_code->au1_hours_value[i] = value; + } + else + { + BITS_PARSE("seconds_flag[i]", value, ps_bitstrm, 1); + ps_time_code->au1_seconds_flag[i] = value; + + if(ps_time_code->au1_seconds_flag[i]) + { + BITS_PARSE("seconds_value[i]", value, ps_bitstrm, 6); + ps_time_code->au1_seconds_value[i] = value; + + BITS_PARSE("minutes_flag[i]", value, ps_bitstrm, 1); + ps_time_code->au1_minutes_flag[i] = value; + + if(ps_time_code->au1_minutes_flag[i]) + { + BITS_PARSE("minutes_value[i]", value, ps_bitstrm, 6); + ps_time_code->au1_minutes_value[i] = value; + + BITS_PARSE("hours_flag[i]", value, ps_bitstrm, 1); + ps_time_code->au1_hours_flag[i] = value; + + if(ps_time_code->au1_hours_flag[i]) + { + BITS_PARSE("hours_value[i]", value, ps_bitstrm, 5); + ps_time_code->au1_hours_value[i] = value; + } + } + } + } + + BITS_PARSE("time_offset_length[i]", value, ps_bitstrm, 5); + ps_time_code->au1_time_offset_length[i] = value; + + if(ps_time_code->au1_time_offset_length[i] > 0) + { + BITS_PARSE("time_offset_value[i]", value, ps_bitstrm, + ps_time_code->au1_time_offset_length[i]); + ps_time_code->au1_time_offset_value[i] = value; + } + else + { + ps_time_code->au1_time_offset_value[i] = 0; + } + } + } + + return (IHEVCD_ERROR_T)IHEVCD_SUCCESS; +} +IHEVCD_ERROR_T ihevcd_parse_mastering_disp_params_sei(codec_t *ps_codec) +{ + parse_ctxt_t *ps_parse = &ps_codec->s_parse; + bitstrm_t *ps_bitstrm = &ps_parse->s_bitstrm; + UWORD32 value; + mastering_dis_col_vol_sei_params_t *ps_mastering_dis_col_vol; + WORD32 i; + + ps_parse->s_sei_params.i4_sei_mastering_disp_colour_vol_params_present_flags = 1; + + ps_mastering_dis_col_vol = &ps_parse->s_sei_params.s_mastering_dis_col_vol_sei_params; + + for(i = 0; i < 3; i++) + { + BITS_PARSE("display_primaries_x[c]", value, ps_bitstrm, 16); + ps_mastering_dis_col_vol->au2_display_primaries_x[i] = value; + + BITS_PARSE("display_primaries_y[c]", value, ps_bitstrm, 16); + ps_mastering_dis_col_vol->au2_display_primaries_y[i] = value; + } + + BITS_PARSE("white_point_x", value, ps_bitstrm, 16); + ps_mastering_dis_col_vol->u2_white_point_x = value; + + BITS_PARSE("white_point_y", value, ps_bitstrm, 16); + ps_mastering_dis_col_vol->u2_white_point_y = value; + + BITS_PARSE("max_display_mastering_luminance", value, ps_bitstrm, 32); + ps_mastering_dis_col_vol->u4_max_display_mastering_luminance = value; + + BITS_PARSE("min_display_mastering_luminance", value, ps_bitstrm, 32); + ps_mastering_dis_col_vol->u4_min_display_mastering_luminance = value; + + return (IHEVCD_ERROR_T)IHEVCD_SUCCESS; +} + +IHEVCD_ERROR_T ihevcd_parse_user_data_registered_itu_t_t35(codec_t *ps_codec, + UWORD32 u4_payload_size) +{ + parse_ctxt_t *ps_parse = &ps_codec->s_parse; + bitstrm_t *ps_bitstrm = &ps_parse->s_bitstrm; + UWORD32 value; + user_data_registered_itu_t_t35_t *ps_user_data_registered_itu_t_t35; + UWORD32 i; + UWORD32 j = 0; + + ps_parse->s_sei_params.i1_user_data_registered_present_flag = 1; + ps_user_data_registered_itu_t_t35 = + &ps_parse->s_sei_params.as_user_data_registered_itu_t_t35[ps_parse->s_sei_params.i4_sei_user_data_cnt]; + ps_parse->s_sei_params.i4_sei_user_data_cnt++; + + ps_user_data_registered_itu_t_t35->i4_payload_size = u4_payload_size; + + if(u4_payload_size > MAX_USERDATA_PAYLOAD) + { + u4_payload_size = MAX_USERDATA_PAYLOAD; + } + + ps_user_data_registered_itu_t_t35->i4_valid_payload_size = u4_payload_size; + + BITS_PARSE("itu_t_t35_country_code", value, ps_bitstrm, 8); + ps_user_data_registered_itu_t_t35->u1_itu_t_t35_country_code = value; + + if(0xFF != ps_user_data_registered_itu_t_t35->u1_itu_t_t35_country_code) + { + i = 1; + } + else + { + BITS_PARSE("itu_t_t35_country_code_extension_byte", value, ps_bitstrm, + 8); + ps_user_data_registered_itu_t_t35->u1_itu_t_t35_country_code_extension_byte = + value; + + i = 2; + } + + do + { + BITS_PARSE("itu_t_t35_payload_byte", value, ps_bitstrm, 8); + ps_user_data_registered_itu_t_t35->u1_itu_t_t35_payload_byte[j++] = + value; + + i++; + }while(i < u4_payload_size); + + return (IHEVCD_ERROR_T)IHEVCD_SUCCESS; +} + +void ihevcd_parse_sei_payload(codec_t *ps_codec, + UWORD32 u4_payload_type, + UWORD32 u4_payload_size, + WORD8 i1_nal_type) +{ + parse_ctxt_t *ps_parse = &ps_codec->s_parse; + bitstrm_t *ps_bitstrm = &ps_parse->s_bitstrm; + WORD32 payload_bits_remaining = 0; + sps_t *ps_sps; + + UWORD32 i; + + for(i = 0; i < MAX_SPS_CNT; i++) + { + ps_sps = ps_codec->ps_sps_base + i; + if(ps_sps->i1_sps_valid) + { + break; + } + } + if(NULL == ps_sps) + { + return; + } + + if(NAL_PREFIX_SEI == i1_nal_type) + { + switch(u4_payload_type) + { + case SEI_BUFFERING_PERIOD: + ps_parse->s_sei_params.i1_sei_parameters_present_flag = 1; + ihevcd_parse_buffering_period_sei(ps_codec, ps_sps); + break; + + case SEI_PICTURE_TIMING: + ps_parse->s_sei_params.i1_sei_parameters_present_flag = 1; + ihevcd_parse_pic_timing_sei(ps_codec, ps_sps); + break; + + case SEI_TIME_CODE: + ps_parse->s_sei_params.i1_sei_parameters_present_flag = 1; + ihevcd_parse_time_code_sei(ps_codec); + break; + + case SEI_MASTERING_DISPLAY_COLOUR_VOLUME: + ps_parse->s_sei_params.i4_sei_mastering_disp_colour_vol_params_present_flags = 1; + ihevcd_parse_mastering_disp_params_sei(ps_codec); + break; + + case SEI_USER_DATA_REGISTERED_ITU_T_T35: + ps_parse->s_sei_params.i1_sei_parameters_present_flag = 1; + if(ps_parse->s_sei_params.i4_sei_user_data_cnt >= USER_DATA_MAX) + { + for(i = 0; i < u4_payload_size / 4; i++) + { + ihevcd_bits_flush(ps_bitstrm, 4 * 8); + } + + ihevcd_bits_flush(ps_bitstrm, (u4_payload_size - i * 4) * 8); + } + else + { + ihevcd_parse_user_data_registered_itu_t_t35(ps_codec, + u4_payload_size); + } + break; + + default: + for(i = 0; i < u4_payload_size; i++) + { + ihevcd_bits_flush(ps_bitstrm, 8); + } + break; + } + } + else /* NAL_SUFFIX_SEI */ + { + switch(u4_payload_type) + { + case SEI_USER_DATA_REGISTERED_ITU_T_T35: + ps_parse->s_sei_params.i1_sei_parameters_present_flag = 1; + if(ps_parse->s_sei_params.i4_sei_user_data_cnt >= USER_DATA_MAX) + { + for(i = 0; i < u4_payload_size / 4; i++) + { + ihevcd_bits_flush(ps_bitstrm, 4 * 8); + } + + ihevcd_bits_flush(ps_bitstrm, (u4_payload_size - i * 4) * 8); + } + else + { + ihevcd_parse_user_data_registered_itu_t_t35(ps_codec, + u4_payload_size); + } + break; + + default: + for(i = 0; i < u4_payload_size; i++) + { + ihevcd_bits_flush(ps_bitstrm, 8); + } + break; + } + } + + /** + * By definition the underlying bitstream terminates in a byte-aligned manner. + * 1. Extract all bar the last MIN(bitsremaining,nine) bits as reserved_payload_extension_data + * 2. Examine the final 8 bits to determine the payload_bit_equal_to_one marker + * 3. Extract the remainingreserved_payload_extension_data bits. + * + * If there are fewer than 9 bits available, extract them. + */ + + payload_bits_remaining = ihevcd_bits_num_bits_remaining(ps_bitstrm); + if(payload_bits_remaining) /* more_data_in_payload() */ + { + WORD32 final_bits; + WORD32 final_payload_bits = 0; + WORD32 mask = 0xFF; + UWORD32 u4_dummy; + UWORD32 u4_reserved_payload_extension_data; + UNUSED(u4_dummy); + UNUSED(u4_reserved_payload_extension_data); + + while(payload_bits_remaining > 9) + { + BITS_PARSE("reserved_payload_extension_data", + u4_reserved_payload_extension_data, ps_bitstrm, 1); + payload_bits_remaining--; + } + + final_bits = ihevcd_bits_nxt(ps_bitstrm, payload_bits_remaining); + + while(final_bits & (mask >> final_payload_bits)) + { + final_payload_bits++; + continue; + } + + while(payload_bits_remaining > (9 - final_payload_bits)) + { + BITS_PARSE("reserved_payload_extension_data", + u4_reserved_payload_extension_data, ps_bitstrm, 1); + payload_bits_remaining--; + } + + BITS_PARSE("payload_bit_equal_to_one", u4_dummy, ps_bitstrm, 1); + payload_bits_remaining--; + while(payload_bits_remaining) + { + BITS_PARSE("payload_bit_equal_to_zero", u4_dummy, ps_bitstrm, 1); + payload_bits_remaining--; + } + } + + return; +} + +IHEVCD_ERROR_T ihevcd_read_rbsp_trailing_bits(codec_t *ps_codec, + UWORD32 u4_bits_left) +{ + parse_ctxt_t *ps_parse = &ps_codec->s_parse; + UWORD32 value; + WORD32 cnt = 0; + BITS_PARSE("rbsp_stop_one_bit", value, &ps_parse->s_bitstrm, 1); + u4_bits_left--; + if(value != 1) + { + return (IHEVCD_ERROR_T)IHEVCD_FAIL; + } + while(u4_bits_left) + { + BITS_PARSE("rbsp_alignment_zero_bit", value, &ps_parse->s_bitstrm, 1); + u4_bits_left--; + cnt++; + } + ASSERT(cnt < 8); + + return (IHEVCD_ERROR_T)IHEVCD_SUCCESS; +} /** ******************************************************************************* * @@ -2076,10 +2787,56 @@ void ihevcd_copy_pps(codec_t *ps_codec, WORD32 pps_id, WORD32 pps_id_ref) * ******************************************************************************* */ -IHEVCD_ERROR_T ihevcd_parse_sei(codec_t *ps_codec) +IHEVCD_ERROR_T ihevcd_parse_sei(codec_t *ps_codec, nal_header_t *ps_nal) { IHEVCD_ERROR_T ret = (IHEVCD_ERROR_T)IHEVCD_SUCCESS; - UNUSED(ps_codec); + parse_ctxt_t *ps_parse = &ps_codec->s_parse; + UWORD32 u4_payload_type = 0, u4_last_payload_type_byte = 0; + UWORD32 u4_payload_size = 0, u4_last_payload_size_byte = 0; + UWORD32 value; + bitstrm_t *ps_bitstrm = &ps_parse->s_bitstrm; + UWORD32 u4_bits_left; + + u4_bits_left = ihevcd_bits_num_bits_remaining(ps_bitstrm); + + while(u4_bits_left > 8) + { + while(ihevcd_bits_nxt(ps_bitstrm, 8) == 0xFF) + { + ihevcd_bits_flush(ps_bitstrm, 8); /* equal to 0xFF */ + u4_payload_type += 255; + } + + BITS_PARSE("last_payload_type_byte", value, ps_bitstrm, 8); + u4_last_payload_type_byte = value; + + u4_payload_type += u4_last_payload_type_byte; + + while(ihevcd_bits_nxt(ps_bitstrm, 8) == 0xFF) + { + ihevcd_bits_flush(ps_bitstrm, 8); /* equal to 0xFF */ + u4_payload_size += 255; + } + + BITS_PARSE("last_payload_size_byte", value, ps_bitstrm, 8); + u4_last_payload_size_byte = value; + + u4_payload_size += u4_last_payload_size_byte; + u4_bits_left = ihevcd_bits_num_bits_remaining(ps_bitstrm); + u4_payload_size = MIN(u4_payload_size, u4_bits_left / 8); + ihevcd_parse_sei_payload(ps_codec, u4_payload_type, u4_payload_size, + ps_nal->i1_nal_unit_type); + + /* Calculate the bits left in the current payload */ + u4_bits_left = ihevcd_bits_num_bits_remaining(ps_bitstrm); + } + + // read rbsp_trailing_bits + if(u4_bits_left) + { + ihevcd_read_rbsp_trailing_bits(ps_codec, u4_bits_left); + } + return ret; } diff --git a/decoder/ihevcd_parse_headers.h b/decoder/ihevcd_parse_headers.h index 2139f64..6e9870f 100644 --- a/decoder/ihevcd_parse_headers.h +++ b/decoder/ihevcd_parse_headers.h @@ -42,6 +42,13 @@ void ihevcd_copy_slice_hdr(codec_t *ps_codec, WORD32 slice_idx, WORD32 slice_idx IHEVCD_ERROR_T ihevcd_parse_vps(codec_t *ps_codec); IHEVCD_ERROR_T ihevcd_parse_sps(codec_t *ps_codec); IHEVCD_ERROR_T ihevcd_parse_pps(codec_t *ps_codec); +IHEVCD_ERROR_T ihevcd_parse_sei(codec_t *ps_codec, nal_header_t *ps_nal); +IHEVCD_ERROR_T ihevcd_parse_pic_timing_sei(codec_t *ps_codec, sps_t *ps_sps); +IHEVCD_ERROR_T ihevcd_parse_buffering_period_sei(codec_t *ps_codec, sps_t *ps_sps); +IHEVCD_ERROR_T ihevcd_parse_time_code_sei(codec_t *ps_codec); +IHEVCD_ERROR_T ihevcd_parse_user_data_registered_itu_t_t35(codec_t *ps_codec, UWORD32 u4_payload_size); +IHEVCD_ERROR_T ihevcd_parse_active_parameter_sets_sei(codec_t *ps_codec, sps_t *ps_sps); +IHEVCD_ERROR_T ihevcd_read_rbsp_trailing_bits(codec_t *ps_codec, UWORD32 u4_bits_left); IHEVCD_ERROR_T ihevcd_parse_slice_header(codec_t *ps_codec, nal_header_t *ps_nal); diff --git a/decoder/ihevcd_parse_slice_header.c b/decoder/ihevcd_parse_slice_header.c index 8dd3b13..70998f7 100644 --- a/decoder/ihevcd_parse_slice_header.c +++ b/decoder/ihevcd_parse_slice_header.c @@ -470,9 +470,16 @@ IHEVCD_ERROR_T ihevcd_parse_slice_header(codec_t *ps_codec, if(i < ps_slice_hdr->i1_num_long_term_sps) { /* Use CLZ to compute Ceil( Log2( num_long_term_ref_pics_sps ) ) */ - WORD32 num_bits = 32 - CLZ(ps_sps->i1_num_long_term_ref_pics_sps); - BITS_PARSE("lt_idx_sps[ i ]", value, ps_bitstrm, num_bits); - ps_slice_hdr->ai4_poc_lsb_lt[i] = ps_sps->ai1_lt_ref_pic_poc_lsb_sps[value]; + if (ps_sps->i1_num_long_term_ref_pics_sps > 1) + { + WORD32 num_bits = 32 - CLZ(ps_sps->i1_num_long_term_ref_pics_sps - 1); + BITS_PARSE("lt_idx_sps[ i ]", value, ps_bitstrm, num_bits); + } + else + { + value = 0; + } + ps_slice_hdr->ai4_poc_lsb_lt[i] = ps_sps->au2_lt_ref_pic_poc_lsb_sps[value]; ps_slice_hdr->ai1_used_by_curr_pic_lt_flag[i] = ps_sps->ai1_used_by_curr_pic_lt_sps_flag[value]; } diff --git a/decoder/ihevcd_structs.h b/decoder/ihevcd_structs.h index 1a46984..5b0837d 100644 --- a/decoder/ihevcd_structs.h +++ b/decoder/ihevcd_structs.h @@ -1161,7 +1161,10 @@ typedef struct */ WORD32 i4_next_tu_ctb_cnt; - + /** + * SEI parameters + */ + sei_params_t s_sei_params; }parse_ctxt_t; /** diff --git a/decoder/ihevcd_utils.c b/decoder/ihevcd_utils.c index 14c36ba..fef3f74 100755 --- a/decoder/ihevcd_utils.c +++ b/decoder/ihevcd_utils.c @@ -518,6 +518,47 @@ IHEVCD_ERROR_T ihevcd_pic_buf_mgr_add_bufs(codec_t *ps_codec) ps_pic_buf->pu1_chroma = pu1_buf + ps_codec->i4_strd * (PAD_TOP / 2) + PAD_LEFT; pu1_buf += chroma_samples; + /* Pad boundary pixels (one pixel on all sides) */ + /* This ensures SAO does not read uninitialized pixels */ + /* Note these are not used in actual processing */ + { + UWORD8 *pu1_buf; + WORD32 strd, wd, ht; + WORD32 i; + strd = ps_codec->i4_strd; + wd = ps_codec->i4_wd; + ht = ps_codec->i4_ht; + + pu1_buf = ps_pic_buf->pu1_luma; + for(i = 0; i < ht; i++) + { + pu1_buf[-1] = 0; + pu1_buf[wd] = 0; + pu1_buf += strd; + } + pu1_buf = ps_pic_buf->pu1_luma; + memset(pu1_buf - strd - 1, 0, wd + 2); + + pu1_buf += strd * ht; + memset(pu1_buf - 1, 0, wd + 2); + + pu1_buf = ps_pic_buf->pu1_chroma; + ht >>= 1; + for(i = 0; i < ht; i++) + { + pu1_buf[-1] = 0; + pu1_buf[-2] = 0; + pu1_buf[wd] = 0; + pu1_buf[wd + 1] = 0; + pu1_buf += strd; + } + pu1_buf = ps_pic_buf->pu1_chroma; + memset(pu1_buf - strd - 2, 0, wd + 4); + + pu1_buf += strd * ht; + memset(pu1_buf - 2, 0, wd + 4); + } + buf_ret = ihevc_buf_mgr_add((buf_mgr_t *)ps_codec->pv_pic_buf_mgr, ps_pic_buf, i); @@ -886,6 +927,27 @@ IHEVCD_ERROR_T ihevcd_parse_pic_init(codec_t *ps_codec) pu1_buf = ps_cur_pic->pu1_chroma; pu1_cur_pic_chroma = pu1_buf; + + ps_cur_pic->s_sei_params.i1_sei_parameters_present_flag = 0; + if(ps_codec->s_parse.s_sei_params.i1_sei_parameters_present_flag) + { + sei_params_t *ps_sei = &ps_codec->s_parse.s_sei_params; + ps_cur_pic->s_sei_params = ps_codec->s_parse.s_sei_params; + + /* Once sei_params is copied to pic_buf, + * mark sei_params in s_parse as not present, + * this ensures that future frames do not use this data again. + */ + ps_sei->i1_sei_parameters_present_flag = 0; + ps_sei->i1_user_data_registered_present_flag = 0; + ps_sei->i1_aud_present_flag = 0; + ps_sei->i1_time_code_present_flag = 0; + ps_sei->i1_buf_period_params_present_flag = 0; + ps_sei->i1_pic_timing_params_present_flag = 0; + ps_sei->i1_recovery_point_params_present_flag = 0; + ps_sei->i1_active_parameter_set = 0; + ps_sei->i4_sei_mastering_disp_colour_vol_params_present_flags = 0; + } } if(0 == ps_codec->u4_pic_cnt) |