Code: IHEVCD_ERROR_T ihevcd_parse_slice_header(codec_t *ps_codec,
 nal_header_t *ps_nal)

 {
     IHEVCD_ERROR_T ret = (IHEVCD_ERROR_T)IHEVCD_SUCCESS;
     WORD32 value;
    WORD32 i;
     WORD32 sps_id;
 
     pps_t *ps_pps;
 sps_t *ps_sps;
 slice_header_t *ps_slice_hdr;
    WORD32 disable_deblocking_filter_flag;
 bitstrm_t *ps_bitstrm = &ps_codec->s_parse.s_bitstrm;
    WORD32 idr_pic_flag;
    WORD32 pps_id;
    WORD32 first_slice_in_pic_flag;
    WORD32 no_output_of_prior_pics_flag = 0;
    WORD8 i1_nal_unit_type = ps_nal->i1_nal_unit_type;
    WORD32 num_poc_total_curr = 0;
    WORD32 slice_address;

 if(ps_codec->i4_slice_error == 1)
 return ret;

    idr_pic_flag = (NAL_IDR_W_LP == i1_nal_unit_type) ||
 (NAL_IDR_N_LP == i1_nal_unit_type);


    BITS_PARSE("first_slice_in_pic_flag", first_slice_in_pic_flag, ps_bitstrm, 1);
 if((NAL_BLA_W_LP <= i1_nal_unit_type) &&
 (NAL_RSV_RAP_VCL23          >= i1_nal_unit_type))
 {
        BITS_PARSE("no_output_of_prior_pics_flag", no_output_of_prior_pics_flag, ps_bitstrm, 1);
 }
    UEV_PARSE("pic_parameter_set_id", pps_id, ps_bitstrm);
    pps_id = CLIP3(pps_id, 0, MAX_PPS_CNT - 2);

 /* Get the current PPS structure */
    ps_pps = ps_codec->s_parse.ps_pps_base + pps_id;
 if(0 == ps_pps->i1_pps_valid)
 {
 pps_t *ps_pps_ref = ps_codec->ps_pps_base;
 while(0 == ps_pps_ref->i1_pps_valid)
            ps_pps_ref++;

 if((ps_pps_ref - ps_codec->ps_pps_base >= MAX_PPS_CNT - 1))
 return IHEVCD_INVALID_HEADER;

        ihevcd_copy_pps(ps_codec, pps_id, ps_pps_ref->i1_pps_id);
 }

 /* Get SPS id for the current PPS */
    sps_id = ps_pps->i1_sps_id;

 /* Get the current SPS structure */
    ps_sps = ps_codec->s_parse.ps_sps_base + sps_id;

 /* When the current slice is the first in a pic,
     *  check whether the previous frame is complete
     *  If the previous frame is incomplete -
     *  treat the remaining CTBs as skip */
 if((0 != ps_codec->u4_pic_cnt || ps_codec->i4_pic_present) &&
                    first_slice_in_pic_flag)
 {
 if(ps_codec->i4_pic_present)
 {
 slice_header_t *ps_slice_hdr_next;
            ps_codec->i4_slice_error = 1;
            ps_codec->s_parse.i4_cur_slice_idx--;
 if(ps_codec->s_parse.i4_cur_slice_idx < 0)
                ps_codec->s_parse.i4_cur_slice_idx = 0;

            ps_slice_hdr_next = ps_codec->s_parse.ps_slice_hdr_base + ((ps_codec->s_parse.i4_cur_slice_idx + 1) & (MAX_SLICE_HDR_CNT - 1));
            ps_slice_hdr_next->i2_ctb_x = 0;
            ps_slice_hdr_next->i2_ctb_y = ps_codec->s_parse.ps_sps->i2_pic_ht_in_ctb;
 return ret;
 }
 else
 {
            ps_codec->i4_slice_error = 0;
 }
 }

 if(first_slice_in_pic_flag)
 {
        ps_codec->s_parse.i4_cur_slice_idx = 0;
 }
 else
 {
 /* If the current slice is not the first slice in the pic,
         * but the first one to be parsed, set the current slice indx to 1
         * Treat the first slice to be missing and copy the current slice header
         * to the first one */
 if(0 == ps_codec->i4_pic_present)
            ps_codec->s_parse.i4_cur_slice_idx = 1;
 }

    ps_slice_hdr = ps_codec->s_parse.ps_slice_hdr_base + (ps_codec->s_parse.i4_cur_slice_idx & (MAX_SLICE_HDR_CNT - 1));


 if((ps_pps->i1_dependent_slice_enabled_flag) &&
 (!first_slice_in_pic_flag))
 {
        BITS_PARSE("dependent_slice_flag", value, ps_bitstrm, 1);

 /* If dependendent slice, copy slice header from previous slice */
 if(value && (ps_codec->s_parse.i4_cur_slice_idx > 0))
 {
            ihevcd_copy_slice_hdr(ps_codec,
 (ps_codec->s_parse.i4_cur_slice_idx & (MAX_SLICE_HDR_CNT - 1)),
 ((ps_codec->s_parse.i4_cur_slice_idx - 1) & (MAX_SLICE_HDR_CNT - 1)));
 }
        ps_slice_hdr->i1_dependent_slice_flag = value;
 }
 else
 {
        ps_slice_hdr->i1_dependent_slice_flag = 0;
 }
    ps_slice_hdr->i1_nal_unit_type = i1_nal_unit_type;
    ps_slice_hdr->i1_pps_id = pps_id;
    ps_slice_hdr->i1_first_slice_in_pic_flag = first_slice_in_pic_flag;

    ps_slice_hdr->i1_no_output_of_prior_pics_flag = 1;
 if((NAL_BLA_W_LP <= i1_nal_unit_type) &&
 (NAL_RSV_RAP_VCL23          >= i1_nal_unit_type))
 {
        ps_slice_hdr->i1_no_output_of_prior_pics_flag = no_output_of_prior_pics_flag;
 }
    ps_slice_hdr->i1_pps_id = pps_id;

 if(!ps_slice_hdr->i1_first_slice_in_pic_flag)
 {
        WORD32 num_bits;

 /* Use CLZ to compute Ceil( Log2( PicSizeInCtbsY ) ) */
        num_bits = 32 - CLZ(ps_sps->i4_pic_size_in_ctb - 1);
        BITS_PARSE("slice_address", value, ps_bitstrm, num_bits);

        slice_address = value;
 /* If slice address is greater than the number of CTBs in a picture,
         * ignore the slice */
 if(value >= ps_sps->i4_pic_size_in_ctb)
 return IHEVCD_IGNORE_SLICE;
 }
 else
 {
        slice_address = 0;
 }

 if(!ps_slice_hdr->i1_dependent_slice_flag)
 {
        ps_slice_hdr->i1_pic_output_flag = 1;
        ps_slice_hdr->i4_pic_order_cnt_lsb = 0;
        ps_slice_hdr->i1_num_long_term_sps = 0;
        ps_slice_hdr->i1_num_long_term_pics = 0;

 for(i = 0; i < ps_pps->i1_num_extra_slice_header_bits; i++)
 {
            BITS_PARSE("slice_reserved_undetermined_flag[ i ]", value, ps_bitstrm, 1);
 }
        UEV_PARSE("slice_type", value, ps_bitstrm);
        ps_slice_hdr->i1_slice_type = value;

 /* If the picture is IRAP, slice type must be equal to ISLICE */
 if((ps_slice_hdr->i1_nal_unit_type >= NAL_BLA_W_LP) &&
 (ps_slice_hdr->i1_nal_unit_type <= NAL_RSV_RAP_VCL23))
            ps_slice_hdr->i1_slice_type = ISLICE;

 if((ps_slice_hdr->i1_slice_type < 0) ||
 (ps_slice_hdr->i1_slice_type > 2))
 return IHEVCD_IGNORE_SLICE;

 if(ps_pps->i1_output_flag_present_flag)
 {
            BITS_PARSE("pic_output_flag", value, ps_bitstrm, 1);
            ps_slice_hdr->i1_pic_output_flag = value;
 }
        ps_slice_hdr->i1_colour_plane_id = 0;
 if(1 == ps_sps->i1_separate_colour_plane_flag)
 {
            BITS_PARSE("colour_plane_id", value, ps_bitstrm, 2);
            ps_slice_hdr->i1_colour_plane_id = value;
 }
        ps_slice_hdr->i1_slice_temporal_mvp_enable_flag = 0;

 if(!idr_pic_flag)
 {

            WORD32 st_rps_idx;
            WORD32 num_neg_pics;
            WORD32 num_pos_pics;
            WORD8 *pi1_used;

            BITS_PARSE("pic_order_cnt_lsb", value, ps_bitstrm, ps_sps->i1_log2_max_pic_order_cnt_lsb);
            ps_slice_hdr->i4_pic_order_cnt_lsb = value;

            BITS_PARSE("short_term_ref_pic_set_sps_flag", value, ps_bitstrm, 1);
            ps_slice_hdr->i1_short_term_ref_pic_set_sps_flag = value;

 if(1 == ps_slice_hdr->i1_short_term_ref_pic_set_sps_flag)
 {
                WORD32 numbits;

                ps_slice_hdr->i1_short_term_ref_pic_set_idx = 0;
 if(ps_sps->i1_num_short_term_ref_pic_sets > 1)
 {
                    numbits = 32 - CLZ(ps_sps->i1_num_short_term_ref_pic_sets - 1);
                    BITS_PARSE("short_term_ref_pic_set_idx", value, ps_bitstrm, numbits);
                    ps_slice_hdr->i1_short_term_ref_pic_set_idx = value;
 }

                st_rps_idx = ps_slice_hdr->i1_short_term_ref_pic_set_idx;
                num_neg_pics = ps_sps->as_stref_picset[st_rps_idx].i1_num_neg_pics;
                num_pos_pics = ps_sps->as_stref_picset[st_rps_idx].i1_num_pos_pics;
                pi1_used = ps_sps->as_stref_picset[st_rps_idx].ai1_used;
 }
 else
 {
                ihevcd_short_term_ref_pic_set(ps_bitstrm,
 &ps_sps->as_stref_picset[0],
                                              ps_sps->i1_num_short_term_ref_pic_sets,
                                              ps_sps->i1_num_short_term_ref_pic_sets,
 &ps_slice_hdr->s_stref_picset);

                st_rps_idx = ps_sps->i1_num_short_term_ref_pic_sets;
                num_neg_pics = ps_slice_hdr->s_stref_picset.i1_num_neg_pics;
                num_pos_pics = ps_slice_hdr->s_stref_picset.i1_num_pos_pics;
                pi1_used = ps_slice_hdr->s_stref_picset.ai1_used;
 }

 if(ps_sps->i1_long_term_ref_pics_present_flag)
 {
 if(ps_sps->i1_num_long_term_ref_pics_sps > 0)
 {
                    UEV_PARSE("num_long_term_sps", value, ps_bitstrm);
                    ps_slice_hdr->i1_num_long_term_sps = value;

                    ps_slice_hdr->i1_num_long_term_sps = CLIP3(ps_slice_hdr->i1_num_long_term_sps,
 0, MAX_DPB_SIZE - num_neg_pics - num_pos_pics);
 }
                UEV_PARSE("num_long_term_pics", value, ps_bitstrm);
                ps_slice_hdr->i1_num_long_term_pics = value;
                ps_slice_hdr->i1_num_long_term_pics = CLIP3(ps_slice_hdr->i1_num_long_term_pics,
 0, MAX_DPB_SIZE - num_neg_pics - num_pos_pics -
                                                            ps_slice_hdr->i1_num_long_term_sps);

 for(i = 0; i < (ps_slice_hdr->i1_num_long_term_sps +
                                ps_slice_hdr->i1_num_long_term_pics); i++)
 {
 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];
                        ps_slice_hdr->ai1_used_by_curr_pic_lt_flag[i] = ps_sps->ai1_used_by_curr_pic_lt_sps_flag[value];

 }
 else
 {
                        BITS_PARSE("poc_lsb_lt[ i ]", value, ps_bitstrm, ps_sps->i1_log2_max_pic_order_cnt_lsb);
                        ps_slice_hdr->ai4_poc_lsb_lt[i] = value;

                        BITS_PARSE("used_by_curr_pic_lt_flag[ i ]", value, ps_bitstrm, 1);
                        ps_slice_hdr->ai1_used_by_curr_pic_lt_flag[i] = value;

 }
                    BITS_PARSE("delta_poc_msb_present_flag[ i ]", value, ps_bitstrm, 1);
                    ps_slice_hdr->ai1_delta_poc_msb_present_flag[i] = value;


                    ps_slice_hdr->ai1_delta_poc_msb_cycle_lt[i] = 0;
 if(ps_slice_hdr->ai1_delta_poc_msb_present_flag[i])
 {

                        UEV_PARSE("delata_poc_msb_cycle_lt[ i ]", value, ps_bitstrm);
                        ps_slice_hdr->ai1_delta_poc_msb_cycle_lt[i] = value;
 }

 if((i != 0) && (i != ps_slice_hdr->i1_num_long_term_sps))
 {
                        ps_slice_hdr->ai1_delta_poc_msb_cycle_lt[i] += ps_slice_hdr->ai1_delta_poc_msb_cycle_lt[i - 1];
 }

 }
 }

 for(i = 0; i < num_neg_pics + num_pos_pics; i++)
 {
 if(pi1_used[i])
 {
                    num_poc_total_curr++;
 }
 }
 for(i = 0; i < ps_slice_hdr->i1_num_long_term_sps + ps_slice_hdr->i1_num_long_term_pics; i++)
 {
 if(ps_slice_hdr->ai1_used_by_curr_pic_lt_flag[i])
 {
                    num_poc_total_curr++;
 }
 }


 if(ps_sps->i1_sps_temporal_mvp_enable_flag)
 {
                BITS_PARSE("enable_temporal_mvp_flag", value, ps_bitstrm, 1);
                ps_slice_hdr->i1_slice_temporal_mvp_enable_flag = value;
 }

 }
        ps_slice_hdr->i1_slice_sao_luma_flag = 0;
        ps_slice_hdr->i1_slice_sao_chroma_flag = 0;
 if(ps_sps->i1_sample_adaptive_offset_enabled_flag)
 {
            BITS_PARSE("slice_sao_luma_flag", value, ps_bitstrm, 1);
            ps_slice_hdr->i1_slice_sao_luma_flag = value;

            BITS_PARSE("slice_sao_chroma_flag", value, ps_bitstrm, 1);
            ps_slice_hdr->i1_slice_sao_chroma_flag = value;

 }

        ps_slice_hdr->i1_max_num_merge_cand = 1;
        ps_slice_hdr->i1_cabac_init_flag = 0;

        ps_slice_hdr->i1_num_ref_idx_l0_active = 0;
        ps_slice_hdr->i1_num_ref_idx_l1_active = 0;
        ps_slice_hdr->i1_slice_cb_qp_offset = 0;
        ps_slice_hdr->i1_slice_cr_qp_offset = 0;
 if((PSLICE == ps_slice_hdr->i1_slice_type) ||
 (BSLICE == ps_slice_hdr->i1_slice_type))
 {
            BITS_PARSE("num_ref_idx_active_override_flag", value, ps_bitstrm, 1);
            ps_slice_hdr->i1_num_ref_idx_active_override_flag = value;

 if(ps_slice_hdr->i1_num_ref_idx_active_override_flag)
 {
                UEV_PARSE("num_ref_idx_l0_active_minus1", value, ps_bitstrm);
                ps_slice_hdr->i1_num_ref_idx_l0_active = value + 1;

 if(BSLICE == ps_slice_hdr->i1_slice_type)
 {
                    UEV_PARSE("num_ref_idx_l1_active_minus1", value, ps_bitstrm);
                    ps_slice_hdr->i1_num_ref_idx_l1_active = value + 1;
 }

 }
 else
 {
                ps_slice_hdr->i1_num_ref_idx_l0_active = ps_pps->i1_num_ref_idx_l0_default_active;

 if(BSLICE == ps_slice_hdr->i1_slice_type)
 {
                    ps_slice_hdr->i1_num_ref_idx_l1_active = ps_pps->i1_num_ref_idx_l1_default_active;
 }
 }

            ps_slice_hdr->i1_num_ref_idx_l0_active = CLIP3(ps_slice_hdr->i1_num_ref_idx_l0_active, 0, MAX_DPB_SIZE - 1);
            ps_slice_hdr->i1_num_ref_idx_l1_active = CLIP3(ps_slice_hdr->i1_num_ref_idx_l1_active, 0, MAX_DPB_SIZE - 1);

 if(0 == num_poc_total_curr)
 return IHEVCD_IGNORE_SLICE;
 if((ps_pps->i1_lists_modification_present_flag) && (num_poc_total_curr > 1))
 {
                ihevcd_ref_pic_list_modification(ps_bitstrm,
                                                 ps_slice_hdr, num_poc_total_curr);
 }
 else
 {
                ps_slice_hdr->s_rplm.i1_ref_pic_list_modification_flag_l0 = 0;
                ps_slice_hdr->s_rplm.i1_ref_pic_list_modification_flag_l1 = 0;
 }

 if(BSLICE == ps_slice_hdr->i1_slice_type)
 {
                BITS_PARSE("mvd_l1_zero_flag", value, ps_bitstrm, 1);
                ps_slice_hdr->i1_mvd_l1_zero_flag = value;
 }

            ps_slice_hdr->i1_cabac_init_flag = 0;
 if(ps_pps->i1_cabac_init_present_flag)
 {
                BITS_PARSE("cabac_init_flag", value, ps_bitstrm, 1);
                ps_slice_hdr->i1_cabac_init_flag = value;

 }
            ps_slice_hdr->i1_collocated_from_l0_flag = 1;
            ps_slice_hdr->i1_collocated_ref_idx = 0;
 if(ps_slice_hdr->i1_slice_temporal_mvp_enable_flag)
 {
 if(BSLICE == ps_slice_hdr->i1_slice_type)
 {
                    BITS_PARSE("collocated_from_l0_flag", value, ps_bitstrm, 1);
                    ps_slice_hdr->i1_collocated_from_l0_flag = value;
 }

 if((ps_slice_hdr->i1_collocated_from_l0_flag  && (ps_slice_hdr->i1_num_ref_idx_l0_active > 1)) ||
 (!ps_slice_hdr->i1_collocated_from_l0_flag  && (ps_slice_hdr->i1_num_ref_idx_l1_active > 1)))
 {
                    UEV_PARSE("collocated_ref_idx", value, ps_bitstrm);
                    ps_slice_hdr->i1_collocated_ref_idx = value;
 }

 }
            ps_slice_hdr->i1_collocated_ref_idx = CLIP3(ps_slice_hdr->i1_collocated_ref_idx, 0, MAX_DPB_SIZE - 1);

 if((ps_pps->i1_weighted_pred_flag  && (PSLICE == ps_slice_hdr->i1_slice_type)) ||
 (ps_pps->i1_weighted_bipred_flag  && (BSLICE == ps_slice_hdr->i1_slice_type)))
 {
                ihevcd_parse_pred_wt_ofst(ps_bitstrm, ps_sps, ps_pps, ps_slice_hdr);
 }
            UEV_PARSE("five_minus_max_num_merge_cand", value, ps_bitstrm);
            ps_slice_hdr->i1_max_num_merge_cand = 5 - value;

 }
        ps_slice_hdr->i1_max_num_merge_cand = CLIP3(ps_slice_hdr->i1_max_num_merge_cand, 1, 5);
        SEV_PARSE("slice_qp_delta", value, ps_bitstrm);
        ps_slice_hdr->i1_slice_qp_delta = value;

 if(ps_pps->i1_pic_slice_level_chroma_qp_offsets_present_flag)
 {
            SEV_PARSE("slice_cb_qp_offset", value, ps_bitstrm);
            ps_slice_hdr->i1_slice_cb_qp_offset = value;

            SEV_PARSE("slice_cr_qp_offset", value, ps_bitstrm);
            ps_slice_hdr->i1_slice_cr_qp_offset = value;

 }
        ps_slice_hdr->i1_deblocking_filter_override_flag = 0;
        ps_slice_hdr->i1_slice_disable_deblocking_filter_flag  = ps_pps->i1_pic_disable_deblocking_filter_flag;
        ps_slice_hdr->i1_beta_offset_div2 = ps_pps->i1_beta_offset_div2;
        ps_slice_hdr->i1_tc_offset_div2 = ps_pps->i1_tc_offset_div2;

        disable_deblocking_filter_flag = ps_pps->i1_pic_disable_deblocking_filter_flag;

 if(ps_pps->i1_deblocking_filter_control_present_flag)
 {

 if(ps_pps->i1_deblocking_filter_override_enabled_flag)
 {
                BITS_PARSE("deblocking_filter_override_flag", value, ps_bitstrm, 1);
                ps_slice_hdr->i1_deblocking_filter_override_flag = value;
 }

 if(ps_slice_hdr->i1_deblocking_filter_override_flag)
 {
                BITS_PARSE("slice_disable_deblocking_filter_flag", value, ps_bitstrm, 1);
                ps_slice_hdr->i1_slice_disable_deblocking_filter_flag = value;
                disable_deblocking_filter_flag = ps_slice_hdr->i1_slice_disable_deblocking_filter_flag;

 if(!ps_slice_hdr->i1_slice_disable_deblocking_filter_flag)
 {
                    SEV_PARSE("beta_offset_div2", value, ps_bitstrm);
                    ps_slice_hdr->i1_beta_offset_div2 = value;

                    SEV_PARSE("tc_offset_div2", value, ps_bitstrm);
                    ps_slice_hdr->i1_tc_offset_div2 = value;

 }
 }
 }

        ps_slice_hdr->i1_slice_loop_filter_across_slices_enabled_flag = ps_pps->i1_loop_filter_across_slices_enabled_flag;
 if(ps_pps->i1_loop_filter_across_slices_enabled_flag  &&
 (ps_slice_hdr->i1_slice_sao_luma_flag  ||  ps_slice_hdr->i1_slice_sao_chroma_flag  || !disable_deblocking_filter_flag))
 {
            BITS_PARSE("slice_loop_filter_across_slices_enabled_flag", value, ps_bitstrm, 1);
            ps_slice_hdr->i1_slice_loop_filter_across_slices_enabled_flag = value;
 }

 }

 /* Check sanity of slice */
 if((!first_slice_in_pic_flag) &&
 (ps_codec->i4_pic_present))
 {
 slice_header_t *ps_slice_hdr_base = ps_codec->ps_slice_hdr_base;


 /* According to the standard, the above conditions must be satisfied - But for error resilience,
         * only the following conditions are checked */
 if((ps_slice_hdr_base->i1_pps_id != ps_slice_hdr->i1_pps_id) ||
 (ps_slice_hdr_base->i4_pic_order_cnt_lsb != ps_slice_hdr->i4_pic_order_cnt_lsb))
 {
 return IHEVCD_IGNORE_SLICE;
 }

 }


 if(0 == ps_codec->i4_pic_present)
 {
        ps_slice_hdr->i4_abs_pic_order_cnt = ihevcd_calc_poc(ps_codec, ps_nal, ps_sps->i1_log2_max_pic_order_cnt_lsb, ps_slice_hdr->i4_pic_order_cnt_lsb);
 }
 else
 {
        ps_slice_hdr->i4_abs_pic_order_cnt = ps_codec->s_parse.i4_abs_pic_order_cnt;
 }


 if(!first_slice_in_pic_flag)
 {
 /* Check if the current slice belongs to the same pic (Pic being parsed) */
 if(ps_codec->s_parse.i4_abs_pic_order_cnt == ps_slice_hdr->i4_abs_pic_order_cnt)
 {

 /* If the Next CTB's index is less than the slice address,
             * the previous slice is incomplete.
             * Indicate slice error, and treat the remaining CTBs as skip */
 if(slice_address > ps_codec->s_parse.i4_next_ctb_indx)
 {
 if(ps_codec->i4_pic_present)
 {
                    ps_codec->i4_slice_error = 1;
                    ps_codec->s_parse.i4_cur_slice_idx--;
 if(ps_codec->s_parse.i4_cur_slice_idx < 0)
                        ps_codec->s_parse.i4_cur_slice_idx = 0;

 return ret;
 }
 else
 {
 return IHEVCD_IGNORE_SLICE;
 }
 }
 /* If the slice address is less than the next CTB's index,
             * extra CTBs have been decoded in the previous slice.
             * Ignore the current slice. Treat it as incomplete */
 else if(slice_address < ps_codec->s_parse.i4_next_ctb_indx)
 {
 return IHEVCD_IGNORE_SLICE;
 }
 else
 {
                ps_codec->i4_slice_error = 0;
 }
 }

 /* The current slice does not belong to the pic that is being parsed */
 else
 {
 /* The previous pic is incomplete.
             * Treat the remaining CTBs as skip */
 if(ps_codec->i4_pic_present)
 {
 slice_header_t *ps_slice_hdr_next;
                ps_codec->i4_slice_error = 1;
                ps_codec->s_parse.i4_cur_slice_idx--;
 if(ps_codec->s_parse.i4_cur_slice_idx < 0)
                    ps_codec->s_parse.i4_cur_slice_idx = 0;

                ps_slice_hdr_next = ps_codec->s_parse.ps_slice_hdr_base + ((ps_codec->s_parse.i4_cur_slice_idx + 1) & (MAX_SLICE_HDR_CNT - 1));
                ps_slice_hdr_next->i2_ctb_x = 0;
                ps_slice_hdr_next->i2_ctb_y = ps_codec->s_parse.ps_sps->i2_pic_ht_in_ctb;
 return ret;
 }

 /* If the previous pic is complete,
             * return if the current slice is dependant
             * otherwise, update the parse context's POC */
 else
 {
 if(ps_slice_hdr->i1_dependent_slice_flag)
 return IHEVCD_IGNORE_SLICE;

                ps_codec->s_parse.i4_abs_pic_order_cnt = ps_slice_hdr->i4_abs_pic_order_cnt;
 }
 }
 }

 /* If the slice is the first slice in the pic, update the parse context's POC */
 else
 {
 /* If the first slice is repeated, ignore the second occurrence
         * If any other slice is repeated, the CTB addr will be greater than the slice addr,
         * and hence the second occurrence is ignored */
 if(ps_codec->s_parse.i4_abs_pic_order_cnt == ps_slice_hdr->i4_abs_pic_order_cnt)
 return IHEVCD_IGNORE_SLICE;

        ps_codec->s_parse.i4_abs_pic_order_cnt = ps_slice_hdr->i4_abs_pic_order_cnt;
 }

    ps_slice_hdr->i4_num_entry_point_offsets = 0;
 if((ps_pps->i1_tiles_enabled_flag) ||
 (ps_pps->i1_entropy_coding_sync_enabled_flag))
 {
        UEV_PARSE("num_entry_point_offsets", value, ps_bitstrm);
        ps_slice_hdr->i4_num_entry_point_offsets = value;

 {
            WORD32 max_num_entry_point_offsets;
 if((ps_pps->i1_tiles_enabled_flag) &&
 (ps_pps->i1_entropy_coding_sync_enabled_flag))
 {
                max_num_entry_point_offsets = ps_pps->i1_num_tile_columns * (ps_sps->i2_pic_ht_in_ctb - 1);
 }
 else if(ps_pps->i1_tiles_enabled_flag)
 {
                max_num_entry_point_offsets = ps_pps->i1_num_tile_columns * ps_pps->i1_num_tile_rows;
 }
 else
 {
                max_num_entry_point_offsets = (ps_sps->i2_pic_ht_in_ctb - 1);
 }

            ps_slice_hdr->i4_num_entry_point_offsets = CLIP3(ps_slice_hdr->i4_num_entry_point_offsets,
 0, max_num_entry_point_offsets);
 }

 if(ps_slice_hdr->i4_num_entry_point_offsets > 0)
 {
            UEV_PARSE("offset_len_minus1", value, ps_bitstrm);
            ps_slice_hdr->i1_offset_len = value + 1;

 for(i = 0; i < ps_slice_hdr->i4_num_entry_point_offsets; i++)
 {
                BITS_PARSE("entry_point_offset", value, ps_bitstrm, ps_slice_hdr->i1_offset_len);

 /* TODO: pu4_entry_point_offset needs to be initialized */
 }

 }
 }

 if(ps_pps->i1_slice_header_extension_present_flag)
 {
        UEV_PARSE("slice_header_extension_length", value, ps_bitstrm);
        ps_slice_hdr->i2_slice_header_extension_length = value;


 for(i = 0; i < ps_slice_hdr->i2_slice_header_extension_length; i++)
 {
            BITS_PARSE("slice_header_extension_data_byte", value, ps_bitstrm, 8);
 }

 }

    ihevcd_bits_flush_to_byte_boundary(ps_bitstrm);

 {
 dpb_mgr_t *ps_dpb_mgr = (dpb_mgr_t *)ps_codec->pv_dpb_mgr;
        WORD32 r_idx;

 if((NAL_IDR_W_LP == ps_slice_hdr->i1_nal_unit_type) ||
 (NAL_IDR_N_LP == ps_slice_hdr->i1_nal_unit_type) ||
 (NAL_BLA_N_LP == ps_slice_hdr->i1_nal_unit_type) ||
 (NAL_BLA_W_DLP == ps_slice_hdr->i1_nal_unit_type) ||
 (NAL_BLA_W_LP == ps_slice_hdr->i1_nal_unit_type) ||
 (0 == ps_codec->u4_pic_cnt))
 {
 for(i = 0; i < MAX_DPB_BUFS; i++)
 {
 if(ps_dpb_mgr->as_dpb_info[i].ps_pic_buf)
 {
 pic_buf_t *ps_pic_buf = ps_dpb_mgr->as_dpb_info[i].ps_pic_buf;
 mv_buf_t *ps_mv_buf;

 /* Long term index is set to MAX_DPB_BUFS to ensure it is not added as LT */

                     ihevc_dpb_mgr_del_ref((dpb_mgr_t *)ps_codec->pv_dpb_mgr, (buf_mgr_t *)ps_codec->pv_pic_buf_mgr, ps_pic_buf->i4_abs_poc);
                     /* Find buffer id of the MV bank corresponding to the buffer being freed (Buffer with POC of u4_abs_poc) */
                     ps_mv_buf = (mv_buf_t *)ps_codec->ps_mv_buf;
                    for(i = 0; i < BUF_MGR_MAX_CNT; i++)
                     {
                         if(ps_mv_buf && ps_mv_buf->i4_abs_poc == ps_pic_buf->i4_abs_poc)
                         {
                            ihevc_buf_mgr_release((buf_mgr_t *)ps_codec->pv_mv_buf_mgr, i, BUF_MGR_REF);
                             break;
                         }
                         ps_mv_buf++;
 }

 }

 }

 /* Initialize the reference lists to NULL
             * This is done to take care of the cases where the first pic is not IDR
             * but the reference list is not created for the first pic because
             * pic count is zero leaving the reference list uninitialised  */
 for(r_idx = 0; r_idx < MAX_DPB_SIZE; r_idx++)
 {
                ps_slice_hdr->as_ref_pic_list0[r_idx].pv_pic_buf = NULL;
                ps_slice_hdr->as_ref_pic_list0[r_idx].pv_mv_buf = NULL;

                ps_slice_hdr->as_ref_pic_list1[r_idx].pv_pic_buf = NULL;
                ps_slice_hdr->as_ref_pic_list1[r_idx].pv_mv_buf = NULL;
 }

 }
 else
 {
            ret = ihevcd_ref_list(ps_codec, ps_pps, ps_sps, ps_slice_hdr);
 if ((WORD32)IHEVCD_SUCCESS != ret)
 {
 return ret;
 }

 }

 }

 /* Fill the remaining entries of the reference lists with the nearest POC
     * This is done to handle cases where there is a corruption in the reference index */
 if(ps_codec->i4_pic_present)
 {
 pic_buf_t *ps_pic_buf_ref;
 mv_buf_t *ps_mv_buf_ref;
        WORD32 r_idx;
 dpb_mgr_t *ps_dpb_mgr = (dpb_mgr_t *)ps_codec->pv_dpb_mgr;
 buf_mgr_t *ps_mv_buf_mgr = (buf_mgr_t *)ps_codec->pv_mv_buf_mgr;

        ps_pic_buf_ref = ihevc_dpb_mgr_get_ref_by_nearest_poc(ps_dpb_mgr, ps_slice_hdr->i4_abs_pic_order_cnt);
 if(NULL == ps_pic_buf_ref)
 {
            ps_pic_buf_ref = ps_codec->as_process[0].ps_cur_pic;
            ps_mv_buf_ref = ps_codec->s_parse.ps_cur_mv_buf;
 }
 else
 {
            ps_mv_buf_ref = ihevcd_mv_mgr_get_poc(ps_mv_buf_mgr, ps_pic_buf_ref->i4_abs_poc);
 }

 for(r_idx = 0; r_idx < ps_slice_hdr->i1_num_ref_idx_l0_active; r_idx++)
 {
 if(NULL == ps_slice_hdr->as_ref_pic_list0[r_idx].pv_pic_buf)
 {
                ps_slice_hdr->as_ref_pic_list0[r_idx].pv_pic_buf = (void *)ps_pic_buf_ref;
                ps_slice_hdr->as_ref_pic_list0[r_idx].pv_mv_buf = (void *)ps_mv_buf_ref;
 }
 }

 for(r_idx = ps_slice_hdr->i1_num_ref_idx_l0_active; r_idx < MAX_DPB_SIZE; r_idx++)
 {
            ps_slice_hdr->as_ref_pic_list0[r_idx].pv_pic_buf = (void *)ps_pic_buf_ref;
            ps_slice_hdr->as_ref_pic_list0[r_idx].pv_mv_buf = (void *)ps_mv_buf_ref;
 }

 for(r_idx = 0; r_idx < ps_slice_hdr->i1_num_ref_idx_l1_active; r_idx++)
 {
 if(NULL == ps_slice_hdr->as_ref_pic_list1[r_idx].pv_pic_buf)
 {
                ps_slice_hdr->as_ref_pic_list1[r_idx].pv_pic_buf = (void *)ps_pic_buf_ref;
                ps_slice_hdr->as_ref_pic_list1[r_idx].pv_mv_buf = (void *)ps_mv_buf_ref;
 }
 }

 for(r_idx = ps_slice_hdr->i1_num_ref_idx_l1_active; r_idx < MAX_DPB_SIZE; r_idx++)
 {
            ps_slice_hdr->as_ref_pic_list1[r_idx].pv_pic_buf = (void *)ps_pic_buf_ref;
            ps_slice_hdr->as_ref_pic_list1[r_idx].pv_mv_buf = (void *)ps_mv_buf_ref;
 }
 }

 /* Update slice address in the header */
 if(!ps_slice_hdr->i1_first_slice_in_pic_flag)
 {
        ps_slice_hdr->i2_ctb_x = slice_address % ps_sps->i2_pic_wd_in_ctb;
        ps_slice_hdr->i2_ctb_y = slice_address / ps_sps->i2_pic_wd_in_ctb;

 if(!ps_slice_hdr->i1_dependent_slice_flag)
 {
            ps_slice_hdr->i2_independent_ctb_x = ps_slice_hdr->i2_ctb_x;
            ps_slice_hdr->i2_independent_ctb_y = ps_slice_hdr->i2_ctb_y;
 }
 }
 else
 {
        ps_slice_hdr->i2_ctb_x = 0;
        ps_slice_hdr->i2_ctb_y = 0;

        ps_slice_hdr->i2_independent_ctb_x = 0;
        ps_slice_hdr->i2_independent_ctb_y = 0;
 }

 /* If the first slice in the pic is missing, copy the current slice header to
     * the first slice's header */
 if((!first_slice_in_pic_flag) &&
 (0 == ps_codec->i4_pic_present))
 {
 slice_header_t *ps_slice_hdr_prev = ps_codec->s_parse.ps_slice_hdr_base;
        ihevcd_copy_slice_hdr(ps_codec, 0, (ps_codec->s_parse.i4_cur_slice_idx & (MAX_SLICE_HDR_CNT - 1)));

        ps_codec->i4_slice_error = 1;

        ps_slice_hdr_prev->i2_ctb_x = 0;
        ps_slice_hdr_prev->i2_ctb_y = 0;

        ps_codec->s_parse.i4_ctb_x = 0;
        ps_codec->s_parse.i4_ctb_y = 0;

        ps_codec->s_parse.i4_cur_slice_idx = 0;

 if((ps_slice_hdr->i2_ctb_x == 0) &&
 (ps_slice_hdr->i2_ctb_y == 0))
 {
            ps_slice_hdr->i2_ctb_x++;
 }
 }

 {
 /* If skip B is enabled,
         * ignore pictures that are non-reference
         * TODO: (i1_nal_unit_type < NAL_BLA_W_LP) && (i1_nal_unit_type % 2 == 0) only says it is
         * sub-layer non-reference slice. May need to find a way to detect actual non-reference pictures*/

 if((i1_nal_unit_type < NAL_BLA_W_LP) &&
 (i1_nal_unit_type % 2 == 0))
 {
 if(IVD_SKIP_B == ps_codec->e_pic_skip_mode)
 return IHEVCD_IGNORE_SLICE;
 }

 /* If skip PB is enabled,
         * decode only I slices */
 if((IVD_SKIP_PB == ps_codec->e_pic_skip_mode) &&
 (ISLICE != ps_slice_hdr->i1_slice_type))
 {
 return IHEVCD_IGNORE_SLICE;
 }
 }

 return ret;
}

Vulnerability Type: DoS 
CWE ID: 
Summary: A remote denial of service vulnerability in libhevc in Mediaserver could enable an attacker to use a specially crafted file to cause a device hang or reboot. This issue is rated as High severity due to the possibility of remote denial of service. Product: Android. Versions: 5.0.2, 5.1.1, 6.0, 6.0.1, 7.0, 7.1.1, 7.1.2. Android ID: A-34819017.
Commit Message: Check only allocated mv bufs for releasing from reference

When checking mv bufs for releasing from reference, unallocated
mv bufs were also checked. This issue was fixed by restricting
the loop count to allocated number of mv bufs.

Bug: 34896906
Bug: 34819017

Change-Id: If832f590b301f414d4cd5206414efc61a70c17cb
(cherry picked from commit 23bfe3e06d53ea749073a5d7ceda84239742b2c2)
