Commit message: None
CVE: CVE-2017-0637
CWE: CWE-119
Vulnerability description: A remote code execution vulnerability in libhevc in Mediaserver could enable an attacker using a specially crafted file to cause memory corruption during media file and data processing. This issue is rated as Critical due to the possibility of remote code execution within the context of the Mediaserver process.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-34064500.

Project: Android

static IHEVCD_ERROR_T ihevcd_parse_profile_tier_level_layer(bitstrm_t *ps_bitstrm,
 profile_tier_lvl_t *ps_ptl)
{
    WORD32 value;
    WORD32 i;
    IHEVCD_ERROR_T ret = (IHEVCD_ERROR_T)IHEVCD_SUCCESS;

    BITS_PARSE("XXX_profile_space[]", value, ps_bitstrm, 2);
    ps_ptl->i1_profile_space = value;

    BITS_PARSE("XXX_tier_flag[]", value, ps_bitstrm, 1);
    ps_ptl->i1_tier_flag = value;

    BITS_PARSE("XXX_profile_idc[]", value, ps_bitstrm, 5);
    ps_ptl->i1_profile_idc = value;

 for(i = 0; i < MAX_PROFILE_COMPATBLTY; i++)
 {
        BITS_PARSE("XXX_profile_compatibility_flag[][j]", value, ps_bitstrm, 1);
        ps_ptl->ai1_profile_compatibility_flag[i] = value;
 }

    BITS_PARSE("general_progressive_source_flag", value, ps_bitstrm, 1);
    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;

    BITS_PARSE("general_non_packed_constraint_flag", value, ps_bitstrm, 1);
    ps_ptl->i1_general_progressive_source_flag = value;

    BITS_PARSE("general_frame_only_constraint_flag", value, ps_bitstrm, 1);
    ps_ptl->i1_general_progressive_source_flag = value;

    BITS_PARSE("XXX_reserved_zero_44bits[0..15]", value, ps_bitstrm, 16);

    BITS_PARSE("XXX_reserved_zero_44bits[16..31]", value, ps_bitstrm, 16);

    BITS_PARSE("XXX_reserved_zero_44bits[32..43]", value, ps_bitstrm, 12);
 return ret;
}

Project: Android

IHEVCD_ERROR_T ihevcd_parse_sei(codec_t *ps_codec)
{
    IHEVCD_ERROR_T ret = (IHEVCD_ERROR_T)IHEVCD_SUCCESS;
    UNUSED(ps_codec);
 return ret;
}

Project: Android

IHEVCD_ERROR_T ihevcd_parse_sps(codec_t *ps_codec)
{
    IHEVCD_ERROR_T ret = (IHEVCD_ERROR_T)IHEVCD_SUCCESS;
    WORD32 value;

    WORD32 i;
    WORD32 vps_id;
    WORD32 sps_max_sub_layers;
    WORD32 sps_id;
    WORD32 sps_temporal_id_nesting_flag;
 sps_t *ps_sps;
 profile_tier_lvl_info_t s_ptl;
 bitstrm_t *ps_bitstrm = &ps_codec->s_parse.s_bitstrm;
    WORD32 ctb_log2_size_y = 0;


    BITS_PARSE("video_parameter_set_id", value, ps_bitstrm, 4);
    vps_id = value;
    vps_id = CLIP3(vps_id, 0, MAX_VPS_CNT - 1);

    BITS_PARSE("sps_max_sub_layers_minus1", value, ps_bitstrm, 3);
    sps_max_sub_layers = value + 1;
    sps_max_sub_layers = CLIP3(sps_max_sub_layers, 1, 7);

    BITS_PARSE("sps_temporal_id_nesting_flag", value, ps_bitstrm, 1);
    sps_temporal_id_nesting_flag = value;

    ret = ihevcd_profile_tier_level(ps_bitstrm, &(s_ptl), 1,
 (sps_max_sub_layers - 1));

    UEV_PARSE("seq_parameter_set_id", value, ps_bitstrm);
    sps_id = value;

 if((sps_id >= MAX_SPS_CNT) || (sps_id < 0))
 {
 if(ps_codec->i4_sps_done)
 return IHEVCD_UNSUPPORTED_SPS_ID;
 else
            sps_id = 0;
 }


    ps_sps = (ps_codec->s_parse.ps_sps_base + MAX_SPS_CNT - 1);
    ps_sps->i1_sps_id = sps_id;
    ps_sps->i1_vps_id = vps_id;
    ps_sps->i1_sps_max_sub_layers = sps_max_sub_layers;
    ps_sps->i1_sps_temporal_id_nesting_flag = sps_temporal_id_nesting_flag;
 /* This is used only during initialization to get reorder count etc */
    ps_codec->i4_sps_id = sps_id;
    memcpy(&ps_sps->s_ptl, &s_ptl, sizeof(profile_tier_lvl_info_t));

    UEV_PARSE("chroma_format_idc", value, ps_bitstrm);
    ps_sps->i1_chroma_format_idc = value;

 if(ps_sps->i1_chroma_format_idc != CHROMA_FMT_IDC_YUV420)
 {
        ps_codec->s_parse.i4_error_code = IHEVCD_UNSUPPORTED_CHROMA_FMT_IDC;
 return (IHEVCD_ERROR_T)IHEVCD_UNSUPPORTED_CHROMA_FMT_IDC;
 }

 if(CHROMA_FMT_IDC_YUV444_PLANES == ps_sps->i1_chroma_format_idc)
 {
        BITS_PARSE("separate_colour_plane_flag", value, ps_bitstrm, 1);
        ps_sps->i1_separate_colour_plane_flag = value;
 }
 else
 {
        ps_sps->i1_separate_colour_plane_flag = 0;
 }

    UEV_PARSE("pic_width_in_luma_samples", value, ps_bitstrm);
    ps_sps->i2_pic_width_in_luma_samples = value;

    UEV_PARSE("pic_height_in_luma_samples", value, ps_bitstrm);
    ps_sps->i2_pic_height_in_luma_samples = value;

 if((0 >= ps_sps->i2_pic_width_in_luma_samples) || (0 >= ps_sps->i2_pic_height_in_luma_samples))
 return IHEVCD_INVALID_PARAMETER;

 /* i2_pic_width_in_luma_samples and i2_pic_height_in_luma_samples
       should be multiples of min_cb_size. Here these are aligned to 8,
       i.e. smallest CB size */
    ps_sps->i2_pic_width_in_luma_samples = ALIGN8(ps_sps->i2_pic_width_in_luma_samples);
    ps_sps->i2_pic_height_in_luma_samples = ALIGN8(ps_sps->i2_pic_height_in_luma_samples);

    BITS_PARSE("pic_cropping_flag", value, ps_bitstrm, 1);
    ps_sps->i1_pic_cropping_flag = value;

 if(ps_sps->i1_pic_cropping_flag)
 {

        UEV_PARSE("pic_crop_left_offset", value, ps_bitstrm);
        ps_sps->i2_pic_crop_left_offset = value;

        UEV_PARSE("pic_crop_right_offset", value, ps_bitstrm);
        ps_sps->i2_pic_crop_right_offset = value;

        UEV_PARSE("pic_crop_top_offset", value, ps_bitstrm);
        ps_sps->i2_pic_crop_top_offset = value;

        UEV_PARSE("pic_crop_bottom_offset", value, ps_bitstrm);
        ps_sps->i2_pic_crop_bottom_offset = value;
 }
 else
 {
        ps_sps->i2_pic_crop_left_offset = 0;
        ps_sps->i2_pic_crop_right_offset = 0;
        ps_sps->i2_pic_crop_top_offset = 0;
        ps_sps->i2_pic_crop_bottom_offset = 0;
 }


    UEV_PARSE("bit_depth_luma_minus8", value, ps_bitstrm);
 if(0 != value)
 return IHEVCD_UNSUPPORTED_BIT_DEPTH;

    UEV_PARSE("bit_depth_chroma_minus8", value, ps_bitstrm);
 if(0 != value)
 return IHEVCD_UNSUPPORTED_BIT_DEPTH;

    UEV_PARSE("log2_max_pic_order_cnt_lsb_minus4", value, ps_bitstrm);
    ps_sps->i1_log2_max_pic_order_cnt_lsb = value + 4;

    BITS_PARSE("sps_sub_layer_ordering_info_present_flag", value, ps_bitstrm, 1);
    ps_sps->i1_sps_sub_layer_ordering_info_present_flag = value;


    i = (ps_sps->i1_sps_sub_layer_ordering_info_present_flag ? 0 : (ps_sps->i1_sps_max_sub_layers - 1));
 for(; i < ps_sps->i1_sps_max_sub_layers; i++)
 {
        UEV_PARSE("max_dec_pic_buffering", value, ps_bitstrm);
        ps_sps->ai1_sps_max_dec_pic_buffering[i] = value + 1;

 if(ps_sps->ai1_sps_max_dec_pic_buffering[i] > MAX_DPB_SIZE)
 {
 return IHEVCD_INVALID_PARAMETER;
 }

        UEV_PARSE("num_reorder_pics", value, ps_bitstrm);
        ps_sps->ai1_sps_max_num_reorder_pics[i] = value;

 if(ps_sps->ai1_sps_max_num_reorder_pics[i] > ps_sps->ai1_sps_max_dec_pic_buffering[i])
 {
 return IHEVCD_INVALID_PARAMETER;
 }

        UEV_PARSE("max_latency_increase", value, ps_bitstrm);
        ps_sps->ai1_sps_max_latency_increase[i] = value;
 }
    UEV_PARSE("log2_min_coding_block_size_minus3", value, ps_bitstrm);
    ps_sps->i1_log2_min_coding_block_size = value + 3;

    UEV_PARSE("log2_diff_max_min_coding_block_size", value, ps_bitstrm);
    ps_sps->i1_log2_diff_max_min_coding_block_size = value;

    ctb_log2_size_y = ps_sps->i1_log2_min_coding_block_size + ps_sps->i1_log2_diff_max_min_coding_block_size;

    UEV_PARSE("log2_min_transform_block_size_minus2", value, ps_bitstrm);
    ps_sps->i1_log2_min_transform_block_size = value + 2;

    UEV_PARSE("log2_diff_max_min_transform_block_size", value, ps_bitstrm);
    ps_sps->i1_log2_diff_max_min_transform_block_size = value;

    ps_sps->i1_log2_max_transform_block_size = ps_sps->i1_log2_min_transform_block_size +
                    ps_sps->i1_log2_diff_max_min_transform_block_size;

 if ((ps_sps->i1_log2_max_transform_block_size < 0) ||
 (ps_sps->i1_log2_max_transform_block_size > MIN(ctb_log2_size_y, 5)))
 {
 return IHEVCD_INVALID_PARAMETER;
 }

    ps_sps->i1_log2_ctb_size = ps_sps->i1_log2_min_coding_block_size +
                    ps_sps->i1_log2_diff_max_min_coding_block_size;

 if((ps_sps->i1_log2_min_coding_block_size < 3) ||
 (ps_sps->i1_log2_min_transform_block_size < 2) ||
 (ps_sps->i1_log2_diff_max_min_transform_block_size < 0) ||
 (ps_sps->i1_log2_max_transform_block_size > ps_sps->i1_log2_ctb_size) ||
 (ps_sps->i1_log2_ctb_size < 4) ||
 (ps_sps->i1_log2_ctb_size > 6))
 {
 return IHEVCD_INVALID_PARAMETER;
 }

    ps_sps->i1_log2_min_pcm_coding_block_size = 0;
    ps_sps->i1_log2_diff_max_min_pcm_coding_block_size = 0;

    UEV_PARSE("max_transform_hierarchy_depth_inter", value, ps_bitstrm);
    ps_sps->i1_max_transform_hierarchy_depth_inter = value;

    UEV_PARSE("max_transform_hierarchy_depth_intra", value, ps_bitstrm);
    ps_sps->i1_max_transform_hierarchy_depth_intra = value;

 /* String has a d (enabled) in order to match with HM */
    BITS_PARSE("scaling_list_enabled_flag", value, ps_bitstrm, 1);
    ps_sps->i1_scaling_list_enable_flag = value;

 if(ps_sps->i1_scaling_list_enable_flag)
 {
        COPY_DEFAULT_SCALING_LIST(ps_sps->pi2_scaling_mat);
        BITS_PARSE("sps_scaling_list_data_present_flag", value, ps_bitstrm, 1);
        ps_sps->i1_sps_scaling_list_data_present_flag = value;

 if(ps_sps->i1_sps_scaling_list_data_present_flag)
            ihevcd_scaling_list_data(ps_codec, ps_sps->pi2_scaling_mat);
 }
 else
 {
        COPY_FLAT_SCALING_LIST(ps_sps->pi2_scaling_mat);
 }
 /* String is asymmetric_motion_partitions_enabled_flag instead of amp_enabled_flag in order to match with HM */
    BITS_PARSE("asymmetric_motion_partitions_enabled_flag", value, ps_bitstrm, 1);
    ps_sps->i1_amp_enabled_flag = value;

    BITS_PARSE("sample_adaptive_offset_enabled_flag", value, ps_bitstrm, 1);
    ps_sps->i1_sample_adaptive_offset_enabled_flag = value;

    BITS_PARSE("pcm_enabled_flag", value, ps_bitstrm, 1);
    ps_sps->i1_pcm_enabled_flag = value;

 if(ps_sps->i1_pcm_enabled_flag)
 {
        BITS_PARSE("pcm_sample_bit_depth_luma", value, ps_bitstrm, 4);
        ps_sps->i1_pcm_sample_bit_depth_luma = value + 1;

        BITS_PARSE("pcm_sample_bit_depth_chroma", value, ps_bitstrm, 4);
        ps_sps->i1_pcm_sample_bit_depth_chroma = value + 1;

        UEV_PARSE("log2_min_pcm_coding_block_size_minus3", value, ps_bitstrm);
        ps_sps->i1_log2_min_pcm_coding_block_size = value + 3;

        UEV_PARSE("log2_diff_max_min_pcm_coding_block_size", value, ps_bitstrm);
        ps_sps->i1_log2_diff_max_min_pcm_coding_block_size = value;
        BITS_PARSE("pcm_loop_filter_disable_flag", value, ps_bitstrm, 1);
        ps_sps->i1_pcm_loop_filter_disable_flag = value;

 }
    UEV_PARSE("num_short_term_ref_pic_sets", value, ps_bitstrm);
    ps_sps->i1_num_short_term_ref_pic_sets = value;

    ps_sps->i1_num_short_term_ref_pic_sets = CLIP3(ps_sps->i1_num_short_term_ref_pic_sets, 0, MAX_STREF_PICS_SPS);

 for(i = 0; i < ps_sps->i1_num_short_term_ref_pic_sets; i++)
        ihevcd_short_term_ref_pic_set(ps_bitstrm, &ps_sps->as_stref_picset[0], ps_sps->i1_num_short_term_ref_pic_sets, i, &ps_sps->as_stref_picset[i]);

    BITS_PARSE("long_term_ref_pics_present_flag", value, ps_bitstrm, 1);
    ps_sps->i1_long_term_ref_pics_present_flag = value;

 if(ps_sps->i1_long_term_ref_pics_present_flag)
 {
        UEV_PARSE("num_long_term_ref_pics_sps", value, ps_bitstrm);
        ps_sps->i1_num_long_term_ref_pics_sps = value;

 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;

            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;
 }
 }

    BITS_PARSE("sps_temporal_mvp_enable_flag", value, ps_bitstrm, 1);
    ps_sps->i1_sps_temporal_mvp_enable_flag = value;

 /* Print matches HM 8-2 */
    BITS_PARSE("sps_strong_intra_smoothing_enable_flag", value, ps_bitstrm, 1);
    ps_sps->i1_strong_intra_smoothing_enable_flag = value;

    BITS_PARSE("vui_parameters_present_flag", value, ps_bitstrm, 1);
    ps_sps->i1_vui_parameters_present_flag = value;

 if(ps_sps->i1_vui_parameters_present_flag)
        ihevcd_parse_vui_parameters(ps_bitstrm,
 &ps_sps->s_vui_parameters,
                                    ps_sps->i1_sps_max_sub_layers - 1);

    BITS_PARSE("sps_extension_flag", value, ps_bitstrm, 1);

 if((UWORD8 *)ps_bitstrm->pu4_buf > ps_bitstrm->pu1_buf_max)
 {
 return IHEVCD_INVALID_PARAMETER;
 }

 {
        WORD32 numerator;
        WORD32 ceil_offset;

        ceil_offset = (1 << ps_sps->i1_log2_ctb_size) - 1;
        numerator = ps_sps->i2_pic_width_in_luma_samples;

        ps_sps->i2_pic_wd_in_ctb = ((numerator + ceil_offset) /
 (1 << ps_sps->i1_log2_ctb_size));

        numerator = ps_sps->i2_pic_height_in_luma_samples;
        ps_sps->i2_pic_ht_in_ctb = ((numerator + ceil_offset) /
 (1 << ps_sps->i1_log2_ctb_size));

        ps_sps->i4_pic_size_in_ctb = ps_sps->i2_pic_ht_in_ctb *
                        ps_sps->i2_pic_wd_in_ctb;

 if(0 == ps_codec->i4_sps_done)
            ps_codec->s_parse.i4_next_ctb_indx = ps_sps->i4_pic_size_in_ctb;

        numerator = ps_sps->i2_pic_width_in_luma_samples;
        ps_sps->i2_pic_wd_in_min_cb = numerator  /
 (1 << ps_sps->i1_log2_min_coding_block_size);

        numerator = ps_sps->i2_pic_height_in_luma_samples;
        ps_sps->i2_pic_ht_in_min_cb = numerator  /
 (1 << ps_sps->i1_log2_min_coding_block_size);
 }
 if((0 != ps_codec->i4_first_pic_done) &&
 ((ps_codec->i4_wd != ps_sps->i2_pic_width_in_luma_samples) ||
 (ps_codec->i4_ht != ps_sps->i2_pic_height_in_luma_samples)))
 {
        ps_codec->i4_reset_flag = 1;
 return (IHEVCD_ERROR_T)IVD_RES_CHANGED;
 }

 /* Update display width and display height */
 {
        WORD32 disp_wd, disp_ht;
        WORD32 crop_unit_x, crop_unit_y;
        crop_unit_x = 1;
        crop_unit_y = 1;

 if(CHROMA_FMT_IDC_YUV420 == ps_sps->i1_chroma_format_idc)
 {
            crop_unit_x = 2;
            crop_unit_y = 2;
 }

        disp_wd = ps_sps->i2_pic_width_in_luma_samples;
        disp_wd -= ps_sps->i2_pic_crop_left_offset * crop_unit_x;
        disp_wd -= ps_sps->i2_pic_crop_right_offset * crop_unit_x;


        disp_ht = ps_sps->i2_pic_height_in_luma_samples;
        disp_ht -= ps_sps->i2_pic_crop_top_offset * crop_unit_y;
        disp_ht -= ps_sps->i2_pic_crop_bottom_offset * crop_unit_y;

 if((0 >= disp_wd) || (0 >= disp_ht))
 return IHEVCD_INVALID_PARAMETER;

        ps_codec->i4_disp_wd = disp_wd;
        ps_codec->i4_disp_ht = disp_ht;


        ps_codec->i4_wd = ps_sps->i2_pic_width_in_luma_samples;
        ps_codec->i4_ht = ps_sps->i2_pic_height_in_luma_samples;

 {
            WORD32 ref_strd;
            ref_strd = ALIGN32(ps_sps->i2_pic_width_in_luma_samples + PAD_WD);
 if(ps_codec->i4_strd < ref_strd)
 {
                ps_codec->i4_strd = ref_strd;
 }
 }

 if(0 == ps_codec->i4_share_disp_buf)
 {
 if(ps_codec->i4_disp_strd < ps_codec->i4_disp_wd)
 {
                ps_codec->i4_disp_strd = ps_codec->i4_disp_wd;
 }
 }
 else
 {
 if(ps_codec->i4_disp_strd < ps_codec->i4_strd)
 {
                ps_codec->i4_disp_strd = ps_codec->i4_strd;
 }
 }
 }

    ps_codec->i4_sps_done = 1;
 return ret;
}

Project: Android

static WORD32 ihevcd_parse_vui_parameters(bitstrm_t *ps_bitstrm,
 vui_t *ps_vui,
                                          WORD32 sps_max_sub_layers_minus1)
{
    WORD32 ret = (IHEVCD_ERROR_T)IHEVCD_SUCCESS;

    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;
 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)
 {
            BITS_PARSE("sar_width", ps_vui->u2_sar_width, ps_bitstrm, 16);
            BITS_PARSE("sar_height", ps_vui->u2_sar_height, ps_bitstrm, 16);
 }
 }

    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)
        BITS_PARSE("overscan_appropriate_flag", ps_vui->u1_overscan_appropriate_flag, ps_bitstrm, 1);

    BITS_PARSE("video_signal_type_present_flag", ps_vui->u1_video_signal_type_present_flag, ps_bitstrm, 1);
    ps_vui->u1_video_format = VID_FMT_UNSPECIFIED;
    ps_vui->u1_video_full_range_flag = 0;
    ps_vui->u1_colour_description_present_flag = 0;
    ps_vui->u1_colour_primaries = 2;
    ps_vui->u1_transfer_characteristics = 2;
    ps_vui->u1_matrix_coefficients = 2;

 if(ps_vui->u1_video_signal_type_present_flag)
 {
        BITS_PARSE("video_format", ps_vui->u1_video_format, ps_bitstrm, 3);
        BITS_PARSE("video_full_range_flag", ps_vui->u1_video_full_range_flag, ps_bitstrm, 1);
        BITS_PARSE("colour_description_present_flag", ps_vui->u1_colour_description_present_flag, ps_bitstrm, 1);
 if(ps_vui->u1_colour_description_present_flag)
 {
            BITS_PARSE("colour_primaries", ps_vui->u1_colour_primaries, ps_bitstrm, 8);
            BITS_PARSE("transfer_characteristics", ps_vui->u1_transfer_characteristics, ps_bitstrm, 8);
            BITS_PARSE("matrix_coeffs", ps_vui->u1_matrix_coefficients, ps_bitstrm, 8);
 }
 }

    BITS_PARSE("chroma_loc_info_present_flag", ps_vui->u1_chroma_loc_info_present_flag, ps_bitstrm, 1);
    ps_vui->u1_chroma_sample_loc_type_top_field = 0;
    ps_vui->u1_chroma_sample_loc_type_bottom_field = 0;
 if(ps_vui->u1_chroma_loc_info_present_flag)
 {
        UEV_PARSE("chroma_sample_loc_type_top_field", ps_vui->u1_chroma_sample_loc_type_top_field, ps_bitstrm);
        UEV_PARSE("chroma_sample_loc_type_bottom_field", ps_vui->u1_chroma_sample_loc_type_bottom_field, ps_bitstrm);
 }

    BITS_PARSE("neutral_chroma_indication_flag", ps_vui->u1_neutral_chroma_indication_flag, ps_bitstrm, 1);
    BITS_PARSE("field_seq_flag", ps_vui->u1_field_seq_flag, ps_bitstrm, 1);
    BITS_PARSE("frame_field_info_present_flag", ps_vui->u1_frame_field_info_present_flag, ps_bitstrm, 1);
    BITS_PARSE("default_display_window_flag", ps_vui->u1_default_display_window_flag, ps_bitstrm, 1);
    ps_vui->u4_def_disp_win_left_offset = 0;
    ps_vui->u4_def_disp_win_right_offset = 0;
    ps_vui->u4_def_disp_win_top_offset = 0;
    ps_vui->u4_def_disp_win_bottom_offset = 0;
 if(ps_vui->u1_default_display_window_flag)
 {
        UEV_PARSE("def_disp_win_left_offset", ps_vui->u4_def_disp_win_left_offset, ps_bitstrm);
        UEV_PARSE("def_disp_win_right_offset", ps_vui->u4_def_disp_win_right_offset, ps_bitstrm);
        UEV_PARSE("def_disp_win_top_offset", ps_vui->u4_def_disp_win_top_offset, ps_bitstrm);
        UEV_PARSE("def_disp_win_bottom_offset", ps_vui->u4_def_disp_win_bottom_offset, ps_bitstrm);
 }

    BITS_PARSE("vui_timing_info_present_flag", ps_vui->u1_vui_timing_info_present_flag, ps_bitstrm, 1);
 if(ps_vui->u1_vui_timing_info_present_flag)
 {
        BITS_PARSE("vui_num_units_in_tick", ps_vui->u4_vui_num_units_in_tick, ps_bitstrm, 32);
        BITS_PARSE("vui_time_scale", ps_vui->u4_vui_time_scale, ps_bitstrm, 32);
        BITS_PARSE("vui_poc_proportional_to_timing_flag", ps_vui->u1_poc_proportional_to_timing_flag, ps_bitstrm, 1);
 if(ps_vui->u1_poc_proportional_to_timing_flag)
            UEV_PARSE("vui_num_ticks_poc_diff_one_minus1", ps_vui->u1_num_ticks_poc_diff_one_minus1, ps_bitstrm);

        BITS_PARSE("vui_hrd_parameters_present_flag", ps_vui->u1_vui_hrd_parameters_present_flag, ps_bitstrm, 1);
 if(ps_vui->u1_vui_hrd_parameters_present_flag)
            ihevcd_parse_hrd_parameters(ps_bitstrm, &ps_vui->s_vui_hrd_parameters, 1, sps_max_sub_layers_minus1);
 }

    BITS_PARSE("bitstream_restriction_flag", ps_vui->u1_bitstream_restriction_flag, ps_bitstrm, 1);
    ps_vui->u1_tiles_fixed_structure_flag = 0;
    ps_vui->u1_motion_vectors_over_pic_boundaries_flag = 1;
    ps_vui->u1_restricted_ref_pic_lists_flag = 0;
    ps_vui->u4_min_spatial_segmentation_idc = 0;
    ps_vui->u1_max_bytes_per_pic_denom = 2;
    ps_vui->u1_max_bits_per_mincu_denom = 1;
    ps_vui->u1_log2_max_mv_length_horizontal = 15;
    ps_vui->u1_log2_max_mv_length_vertical = 15;
 if(ps_vui->u1_bitstream_restriction_flag)
 {
        BITS_PARSE("tiles_fixed_structure_flag", ps_vui->u1_tiles_fixed_structure_flag, ps_bitstrm, 1);
        BITS_PARSE("motion_vectors_over_pic_boundaries_flag", ps_vui->u1_motion_vectors_over_pic_boundaries_flag, ps_bitstrm, 1);
        BITS_PARSE("restricted_ref_pic_lists_flag", ps_vui->u1_restricted_ref_pic_lists_flag, ps_bitstrm, 1);

        UEV_PARSE("min_spatial_segmentation_idc", ps_vui->u4_min_spatial_segmentation_idc, ps_bitstrm);
        UEV_PARSE("max_bytes_per_pic_denom", ps_vui->u1_max_bytes_per_pic_denom, ps_bitstrm);
        UEV_PARSE("max_bits_per_min_cu_denom", ps_vui->u1_max_bits_per_mincu_denom, ps_bitstrm);
        UEV_PARSE("log2_max_mv_length_horizontal", ps_vui->u1_log2_max_mv_length_horizontal, ps_bitstrm);
        UEV_PARSE("log2_max_mv_length_vertical", ps_vui->u1_log2_max_mv_length_vertical, ps_bitstrm);
 }

 return ret;
}

Project: Android

static IHEVCD_ERROR_T ihevcd_profile_tier_level(bitstrm_t *ps_bitstrm,
 profile_tier_lvl_info_t *ps_ptl,
                                                WORD32 profile_present,
                                                WORD32 max_num_sub_layers)
{
    WORD32 value;
    IHEVCD_ERROR_T ret = (IHEVCD_ERROR_T)IHEVCD_SUCCESS;
    WORD32 i;

 if(profile_present)
 {
        ret = ihevcd_parse_profile_tier_level_layer(ps_bitstrm, &ps_ptl->s_ptl_gen);
 }

    BITS_PARSE("general_level_idc", value, ps_bitstrm, 8);
    ps_ptl->s_ptl_gen.u1_level_idc = value;


 for(i = 0; i < max_num_sub_layers; i++)
 {
        BITS_PARSE("sub_layer_profile_present_flag[i]", value, ps_bitstrm, 1);
        ps_ptl->ai1_sub_layer_profile_present_flag[i] = value;

        BITS_PARSE("sub_layer_level_present_flag[i]", value, ps_bitstrm, 1);
        ps_ptl->ai1_sub_layer_level_present_flag[i] = value;
 }

 if(max_num_sub_layers > 0)
 {
 for(i = max_num_sub_layers; i < 8; i++)
 {
            BITS_PARSE("reserved_zero_2bits", value, ps_bitstrm, 2);
 }
 }

 for(i = 0; i < max_num_sub_layers; i++)
 {
 if(ps_ptl->ai1_sub_layer_profile_present_flag[i])
 {
            ret = ihevcd_parse_profile_tier_level_layer(ps_bitstrm,
 &ps_ptl->as_ptl_sub[i]);
 }
 if(ps_ptl->ai1_sub_layer_level_present_flag[i])
 {
            BITS_PARSE("sub_layer_level_idc[i]", value, ps_bitstrm, 8);
            ps_ptl->as_ptl_sub[i].u1_level_idc = value;

 }
 }



 return ret;
}

Project: Android

IHEVCD_ERROR_T ihevcd_short_term_ref_pic_set(bitstrm_t *ps_bitstrm,
 stref_picset_t *ps_stref_picset_base,
                                             WORD32 num_short_term_ref_pic_sets,
                                             WORD32 idx,
 stref_picset_t *ps_stref_picset)
{
    IHEVCD_ERROR_T ret = (IHEVCD_ERROR_T)IHEVCD_SUCCESS;
    WORD32 value;
 stref_picset_t *ps_stref_picset_ref;
    WORD32 delta_idx, delta_rps;
    WORD32 r_idx;
    WORD32 i;
    WORD32 j, k, temp;
 if(idx > 0)
 {
        BITS_PARSE("inter_ref_pic_set_prediction_flag", value, ps_bitstrm, 1);
        ps_stref_picset->i1_inter_ref_pic_set_prediction_flag = value;
 }
 else
        ps_stref_picset->i1_inter_ref_pic_set_prediction_flag = 0;

 if(ps_stref_picset->i1_inter_ref_pic_set_prediction_flag)
 {
        WORD32 delta_rps_sign;
        WORD32 abs_delta_rps;
        WORD32 num_neg_pics = 0;
        WORD32 num_pos_pics = 0;
        WORD32 num_pics = 0;

 if(idx == num_short_term_ref_pic_sets)
 {
            UEV_PARSE("delta_idx_minus1", value, ps_bitstrm);
            delta_idx = value + 1;
 }
 else
 {
            delta_idx = 1;
 }
        r_idx = idx - delta_idx;
        r_idx = CLIP3(r_idx, 0, idx - 1);

        ps_stref_picset_ref = ps_stref_picset_base + r_idx;

        BITS_PARSE("delta_rps_sign", value, ps_bitstrm, 1);
        delta_rps_sign = value;

        UEV_PARSE("abs_delta_rps_minus1", value, ps_bitstrm);
        abs_delta_rps = value + 1;

        delta_rps = (1 - 2 * delta_rps_sign) * (abs_delta_rps);



 for(i = 0; i <= ps_stref_picset_ref->i1_num_delta_pocs; i++)
 {
            WORD32 ref_idc;

 /*****************************************************************/
 /* ref_idc is parsed as below                                    */
 /* bits "1" ref_idc 1                                            */
 /* bits "01" ref_idc 2                                           */
 /* bits "00" ref_idc 0                                           */
 /*****************************************************************/
            BITS_PARSE("used_by_curr_pic_flag", value, ps_bitstrm, 1);
            ref_idc = value;
            ps_stref_picset->ai1_used[num_pics] = value;
 /* If ref_idc is zero check for next bit */
 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))
 {
                WORD32 delta_poc;
                delta_poc = delta_rps;
                delta_poc +=
 ((i < ps_stref_picset_ref->i1_num_delta_pocs) ?
                                ps_stref_picset_ref->ai2_delta_poc[i] :
 0);

                ps_stref_picset->ai2_delta_poc[num_pics] = delta_poc;

 if(delta_poc < 0)
 {
                    num_neg_pics++;
 }
 else
 {
                    num_pos_pics++;
 }
                num_pics++;
 }
            ps_stref_picset->ai1_ref_idc[i] = ref_idc;
 }

        num_neg_pics = CLIP3(num_neg_pics, 0, MAX_DPB_SIZE - 1);
        num_pos_pics = CLIP3(num_pos_pics, 0, (MAX_DPB_SIZE - 1 - num_neg_pics));
        num_pics = num_neg_pics + num_pos_pics;

        ps_stref_picset->i1_num_ref_idc =
                        ps_stref_picset_ref->i1_num_delta_pocs + 1;
        ps_stref_picset->i1_num_delta_pocs = num_pics;
        ps_stref_picset->i1_num_pos_pics = num_pos_pics;
        ps_stref_picset->i1_num_neg_pics = num_neg_pics;


 for(j = 1; j < num_pics; j++)
 {
            WORD32 delta_poc = ps_stref_picset->ai2_delta_poc[j];
            WORD8 i1_used = ps_stref_picset->ai1_used[j];
 for(k = j - 1; k >= 0; k--)
 {
                temp = ps_stref_picset->ai2_delta_poc[k];
 if(delta_poc < temp)
 {
                    ps_stref_picset->ai2_delta_poc[k + 1] = temp;
                    ps_stref_picset->ai1_used[k + 1] = ps_stref_picset->ai1_used[k];
                    ps_stref_picset->ai2_delta_poc[k] = delta_poc;
                    ps_stref_picset->ai1_used[k] = i1_used;
 }
 }
 }
 for(j = 0, k = num_neg_pics - 1; j < num_neg_pics >> 1; j++, k--)
 {
            WORD32 delta_poc = ps_stref_picset->ai2_delta_poc[j];
            WORD8 i1_used = ps_stref_picset->ai1_used[j];
            ps_stref_picset->ai2_delta_poc[j] = ps_stref_picset->ai2_delta_poc[k];
            ps_stref_picset->ai1_used[j] = ps_stref_picset->ai1_used[k];
            ps_stref_picset->ai2_delta_poc[k] = delta_poc;
            ps_stref_picset->ai1_used[k] = i1_used;
 }

 }
 else
 {
        WORD32 prev_poc = 0;
        WORD32 poc;

        UEV_PARSE("num_negative_pics", value, ps_bitstrm);
        ps_stref_picset->i1_num_neg_pics = value;
        ps_stref_picset->i1_num_neg_pics = CLIP3(ps_stref_picset->i1_num_neg_pics,
 0,
                                                 MAX_DPB_SIZE - 1);

        UEV_PARSE("num_positive_pics", value, ps_bitstrm);
        ps_stref_picset->i1_num_pos_pics = value;
        ps_stref_picset->i1_num_pos_pics = CLIP3(ps_stref_picset->i1_num_pos_pics,
 0,
 (MAX_DPB_SIZE - 1 - ps_stref_picset->i1_num_neg_pics));

        ps_stref_picset->i1_num_delta_pocs =
                        ps_stref_picset->i1_num_neg_pics +
                        ps_stref_picset->i1_num_pos_pics;


 for(i = 0; i < ps_stref_picset->i1_num_neg_pics; i++)
 {
            UEV_PARSE("delta_poc_s0_minus1", value, ps_bitstrm);
            poc = prev_poc - (value + 1);
            prev_poc = poc;
            ps_stref_picset->ai2_delta_poc[i] = poc;

            BITS_PARSE("used_by_curr_pic_s0_flag", value, ps_bitstrm, 1);
            ps_stref_picset->ai1_used[i] = value;

 }
        prev_poc = 0;
 for(i = ps_stref_picset->i1_num_neg_pics;
                        i < ps_stref_picset->i1_num_delta_pocs;
                        i++)
 {
            UEV_PARSE("delta_poc_s1_minus1", value, ps_bitstrm);
            poc = prev_poc + (value + 1);
            prev_poc = poc;
            ps_stref_picset->ai2_delta_poc[i] = poc;

            BITS_PARSE("used_by_curr_pic_s1_flag", value, ps_bitstrm, 1);
            ps_stref_picset->ai1_used[i] = value;

 }

 }

 return ret;
}