Commit message: None
CVE: CVE-2017-13185
CWE: CWE-200
Vulnerability description: An information disclosure vulnerability in the Android media framework (libhevc). Product: Android. Versions: 7.0, 7.1.1, 7.1.2, 8.0. Android ID: A-65123471.

Project: Android

IHEVCD_ERROR_T ihevcd_parse_coding_quadtree(codec_t *ps_codec,
                                            WORD32 x0,
                                            WORD32 y0,
                                            WORD32 log2_cb_size,
                                            WORD32 ct_depth)
{
    IHEVCD_ERROR_T ret = (IHEVCD_ERROR_T)IHEVCD_SUCCESS;
 sps_t *ps_sps;
 pps_t *ps_pps;
    WORD32 split_cu_flag;
    WORD32 x1, y1;
    WORD32 cu_pos_x;
    WORD32 cu_pos_y;
 bitstrm_t *ps_bitstrm = &ps_codec->s_parse.s_bitstrm;
 cab_ctxt_t *ps_cabac = &ps_codec->s_parse.s_cabac;
    WORD32 cb_size = 1 << log2_cb_size;
    ps_sps = ps_codec->s_parse.ps_sps;
    ps_pps = ps_codec->s_parse.ps_pps;

 /* Compute CU position with respect to current CTB in (8x8) units */
    cu_pos_x = (x0 - (ps_codec->s_parse.i4_ctb_x << ps_sps->i1_log2_ctb_size)) >> 3;
    cu_pos_y = (y0 - (ps_codec->s_parse.i4_ctb_y << ps_sps->i1_log2_ctb_size)) >> 3;

    ps_codec->s_parse.s_cu.i4_pos_x = cu_pos_x;
    ps_codec->s_parse.s_cu.i4_pos_y = cu_pos_y;

    ps_codec->s_parse.s_cu.i4_log2_cb_size = log2_cb_size;

    ps_codec->s_parse.i4_ct_depth = ct_depth;
 {
        UWORD32 *pu4_ct_depth_top = ps_codec->s_parse.pu4_ct_depth_top;
        UWORD32 u4_ct_depth_left = ps_codec->s_parse.u4_ct_depth_left;
        UWORD32 u4_ct_depth_top = 0;
        UWORD32 u4_mask;
        UWORD32 u4_top_mask, u4_left_mask;
        WORD32  ctxt_idx;
        UWORD32 u4_min_cu_x = x0 / 8;
        UWORD32 u4_min_cu_y = y0 / 8;

        pu4_ct_depth_top += (u4_min_cu_x / 16);




 if(((x0 + (1 << log2_cb_size)) <= ps_sps->i2_pic_width_in_luma_samples) &&
 ((y0 + (1 << log2_cb_size)) <= ps_sps->i2_pic_height_in_luma_samples) &&
 (log2_cb_size > ps_sps->i1_log2_min_coding_block_size))
 {

            ctxt_idx = IHEVC_CAB_SPLIT_CU_FLAG;
 /* Split cu context increment is decided based on left and top Coding tree
             * depth which is stored at frame level
             */
 /* Check if the CTB is in first row in the current slice or tile */
 if((0 != cu_pos_y) ||
 ((0 != ps_codec->s_parse.i4_ctb_slice_y) &&
 (0 != ps_codec->s_parse.i4_ctb_tile_y)))
 {
                u4_ct_depth_top = *pu4_ct_depth_top;
                u4_ct_depth_top >>= ((u4_min_cu_x % 16) * 2);
                u4_ct_depth_top &= 3;

 if((WORD32)u4_ct_depth_top > ct_depth)
                    ctxt_idx++;
 }

 /* Check if the CTB is in first column in the current slice or tile */
 /*****************************************************************/
 /* If cu_pos_x is non-zero then left is available                */
 /* If cu_pos_x is zero then ensure both the following are true   */
 /*    Current CTB is not the first CTB in a tile row             */
 /*    Current CTB is not the first CTB in a slice                */
 /*****************************************************************/
 if((0 != cu_pos_x) ||
 (((0 != ps_codec->s_parse.i4_ctb_slice_x) || (0 != ps_codec->s_parse.i4_ctb_slice_y)) &&
 (0 != ps_codec->s_parse.i4_ctb_tile_x)))
 {
                u4_ct_depth_left >>= ((u4_min_cu_y % 16) * 2);
                u4_ct_depth_left &= 3;
 if((WORD32)u4_ct_depth_left > ct_depth)
                    ctxt_idx++;
 }
            TRACE_CABAC_CTXT("split_cu_flag", ps_cabac->u4_range, ctxt_idx);
            split_cu_flag = ihevcd_cabac_decode_bin(ps_cabac, ps_bitstrm, ctxt_idx);
            AEV_TRACE("split_cu_flag", split_cu_flag, ps_cabac->u4_range);
 }
 else
 {
 if(log2_cb_size > ps_sps->i1_log2_min_coding_block_size)
                split_cu_flag = 1;
 else
                split_cu_flag = 0;
 }

 if(0 == split_cu_flag)
 {
 /* Update top ct_depth */
            u4_ct_depth_top = *pu4_ct_depth_top;
 /* Since Max cb_size is 64, maximum of 8 bits will be set or reset */
 /* Also since Coding block will be within 64x64 grid, only 8bits within a WORD32
             * need to be updated. These 8 bits will not cross 8 bit boundaries
             */
            u4_mask = DUP_LSB_11(cb_size / 8);

            u4_top_mask = u4_mask << ((u4_min_cu_x % 16) * 2);
            u4_ct_depth_top &= ~u4_top_mask;

 if(ct_depth)
 {
                u4_top_mask = gau4_ct_depth_mask[ct_depth] & u4_mask;

                u4_top_mask = u4_top_mask << ((u4_min_cu_x % 16) * 2);
                u4_ct_depth_top |= u4_top_mask;
 }

 *pu4_ct_depth_top = u4_ct_depth_top;

 /* Update left ct_depth */
            u4_ct_depth_left = ps_codec->s_parse.u4_ct_depth_left;

            u4_left_mask = u4_mask << ((u4_min_cu_y % 16) * 2);

            u4_ct_depth_left &= ~u4_left_mask;
 if(ct_depth)
 {
                u4_left_mask = gau4_ct_depth_mask[ct_depth] & u4_mask;

                u4_left_mask = u4_left_mask << ((u4_min_cu_y % 16) * 2);
                u4_ct_depth_left |= u4_left_mask;
 }

            ps_codec->s_parse.u4_ct_depth_left = u4_ct_depth_left;
 }
 }
 if((ps_pps->i1_cu_qp_delta_enabled_flag) &&
 (log2_cb_size >= ps_pps->i1_log2_min_cu_qp_delta_size))
 {
        ps_codec->s_parse.i4_is_cu_qp_delta_coded = 0;
        ps_codec->s_parse.i4_cu_qp_delta = 0;
 }
 if(split_cu_flag)
 {
        x1 = x0 + ((1 << log2_cb_size) >> 1);
        y1 = y0 + ((1 << log2_cb_size) >> 1);

        ret = ihevcd_parse_coding_quadtree(ps_codec, x0, y0, log2_cb_size - 1, ct_depth + 1);
        RETURN_IF((IHEVCD_ERROR_T)IHEVCD_SUCCESS != ret, ret);

 /* At frame boundaries coding quadtree nodes are sent only if they fall within the frame */
 if(x1 < ps_sps->i2_pic_width_in_luma_samples)
 {
            ret = ihevcd_parse_coding_quadtree(ps_codec, x1, y0, log2_cb_size - 1, ct_depth + 1);
            RETURN_IF((IHEVCD_ERROR_T)IHEVCD_SUCCESS != ret, ret);
 }

 if(y1 < ps_sps->i2_pic_height_in_luma_samples)
 {
            ret = ihevcd_parse_coding_quadtree(ps_codec, x0, y1, log2_cb_size - 1, ct_depth + 1);
            RETURN_IF((IHEVCD_ERROR_T)IHEVCD_SUCCESS != ret, ret);
 }

 if((x1 < ps_sps->i2_pic_width_in_luma_samples) &&
 (y1 < ps_sps->i2_pic_height_in_luma_samples))
 {
            ret = ihevcd_parse_coding_quadtree(ps_codec, x1, y1, log2_cb_size - 1, ct_depth + 1);
            RETURN_IF((IHEVCD_ERROR_T)IHEVCD_SUCCESS != ret, ret);
 }
 }
 else
 {
 /* Set current group QP if current CU is aligned with the group */
 {
            WORD32 cu_pos_x = ps_codec->s_parse.s_cu.i4_pos_x << 3;
            WORD32 cu_pos_y = ps_codec->s_parse.s_cu.i4_pos_y << 3;

            WORD32 qpg_x = (cu_pos_x - (cu_pos_x & ((1 << ps_pps->i1_log2_min_cu_qp_delta_size) - 1)));
            WORD32 qpg_y = (cu_pos_y - (cu_pos_y & ((1 << ps_pps->i1_log2_min_cu_qp_delta_size) - 1)));

 if((cu_pos_x == qpg_x) &&
 (cu_pos_y == qpg_y))
 {
                ps_codec->s_parse.u4_qpg = ps_codec->s_parse.u4_qp;

                ps_codec->s_parse.s_cu.i4_cu_qp_delta = 0;

 }
 }

        ret = ihevcd_parse_coding_unit(ps_codec, x0, y0, log2_cb_size);
        RETURN_IF((IHEVCD_ERROR_T)IHEVCD_SUCCESS != ret, ret);

 if(ps_pps->i1_cu_qp_delta_enabled_flag)
 {
            WORD32 qp_pred, qp_left, qp_top;
            WORD32 cu_pos_x;
            WORD32 cu_pos_y;
            WORD32 qpg_x;
            WORD32 qpg_y;
            WORD32 i, j;
            WORD32 qp;
            WORD32 cur_cu_offset;
 tu_t *ps_tu = ps_codec->s_parse.ps_tu;
            WORD32 cb_size = 1 << ps_codec->s_parse.s_cu.i4_log2_cb_size;

            cu_pos_x = ps_codec->s_parse.s_cu.i4_pos_x << 3;
            cu_pos_y = ps_codec->s_parse.s_cu.i4_pos_y << 3;

            qpg_x = (cu_pos_x - (cu_pos_x & ((1 << ps_pps->i1_log2_min_cu_qp_delta_size) - 1))) >> 3;
            qpg_y = (cu_pos_y - (cu_pos_y & ((1 << ps_pps->i1_log2_min_cu_qp_delta_size) - 1))) >> 3;

 /*previous coded Qp*/
            qp_left = ps_codec->s_parse.u4_qpg;
            qp_top = ps_codec->s_parse.u4_qpg;

 if(qpg_x > 0)
 {
                qp_left = ps_codec->s_parse.ai1_8x8_cu_qp[qpg_x - 1 + (qpg_y * 8)];
 }
 if(qpg_y > 0)
 {
                qp_top = ps_codec->s_parse.ai1_8x8_cu_qp[qpg_x + ((qpg_y - 1) * 8)];
 }

            qp_pred = (qp_left + qp_top + 1) >> 1;
 /* Since qp_pred + ps_codec->s_parse.s_cu.i4_cu_qp_delta can be negative,
            52 is added before taking modulo 52 */
            qp = (qp_pred + ps_codec->s_parse.s_cu.i4_cu_qp_delta + 52) % 52;

            cur_cu_offset = (cu_pos_x >> 3) + cu_pos_y;
 for(i = 0; i < (cb_size >> 3); i++)
 {
 for(j = 0; j < (cb_size >> 3); j++)
 {
                    ps_codec->s_parse.ai1_8x8_cu_qp[cur_cu_offset + (i * 8) + j] = qp;
 }
 }

            ps_codec->s_parse.u4_qp = qp;
            ps_codec->s_parse.s_cu.i4_qp = qp;


 /* When change in QP is signaled, update the QP in TUs that are already parsed in the CU */
 {
 tu_t *ps_tu_tmp;
                ps_tu_tmp = ps_tu - ps_codec->s_parse.s_cu.i4_tu_cnt;
                ps_tu->b7_qp = ps_codec->s_parse.u4_qp;
 while(ps_tu_tmp != ps_tu)
 {
                    ps_tu_tmp->b7_qp = ps_codec->s_parse.u4_qp;

                    ps_tu_tmp++;
 }
 }
 if(ps_codec->s_parse.s_cu.i4_cu_qp_delta)
 {
                WORD32 ctb_indx;
                ctb_indx = ps_codec->s_parse.i4_ctb_x + ps_sps->i2_pic_wd_in_ctb * ps_codec->s_parse.i4_ctb_y;
                ps_codec->s_parse.s_bs_ctxt.pu1_pic_qp_const_in_ctb[ctb_indx >> 3] &= (~(1 << (ctb_indx & 7)));
 }

 }

 }




 return ret;
}

Project: Android

IHEVCD_ERROR_T  ihevcd_parse_coding_unit(codec_t *ps_codec,
                                         WORD32 x0,
                                         WORD32 y0,
                                         WORD32 log2_cb_size)
{
    IHEVCD_ERROR_T ret = (IHEVCD_ERROR_T)IHEVCD_SUCCESS;
 sps_t *ps_sps;
 pps_t *ps_pps;
    WORD32 cb_size;
 slice_header_t *ps_slice_hdr;
    WORD32 skip_flag;
    WORD32 pcm_flag;
    UWORD32 *pu4_skip_top = ps_codec->s_parse.pu4_skip_cu_top;
    UWORD32 u4_skip_left = ps_codec->s_parse.u4_skip_cu_left;
 bitstrm_t *ps_bitstrm = &ps_codec->s_parse.s_bitstrm;
 tu_t *ps_tu = ps_codec->s_parse.ps_tu;

    WORD32 cu_pos_x;
    WORD32 cu_pos_y;
 cab_ctxt_t *ps_cabac = &ps_codec->s_parse.s_cabac;

    ASSERT(0 == (x0 % 8));
    ASSERT(0 == (y0 % 8));

    ps_codec->s_parse.s_cu.i4_tu_cnt = 0;
    ps_sps = ps_codec->s_parse.ps_sps;
    ps_pps = ps_codec->s_parse.ps_pps;

    cu_pos_x = ps_codec->s_parse.s_cu.i4_pos_x;
    cu_pos_y = ps_codec->s_parse.s_cu.i4_pos_y;



    ps_slice_hdr = ps_codec->s_parse.ps_slice_hdr;


    cb_size = 1 << log2_cb_size;

    ps_codec->s_parse.s_cu.i4_cu_transquant_bypass = 0;

 if(ps_pps->i1_transquant_bypass_enable_flag)
 {
        TRACE_CABAC_CTXT("cu_transquant_bypass_flag", ps_cabac->u4_range, IHEVC_CAB_CU_TQ_BYPASS_FLAG);
        ps_codec->s_parse.s_cu.i4_cu_transquant_bypass =
                        ihevcd_cabac_decode_bin(ps_cabac, ps_bitstrm,
                                                IHEVC_CAB_CU_TQ_BYPASS_FLAG);
 /* Update transquant_bypass in ps_tu */

        AEV_TRACE("cu_transquant_bypass_flag", ps_codec->s_parse.s_cu.i4_cu_transquant_bypass,
                  ps_cabac->u4_range);

 if(ps_codec->s_parse.s_cu.i4_cu_transquant_bypass)
 {
            UWORD8 *pu1_pic_no_loop_filter_flag = ps_codec->s_parse.pu1_pic_no_loop_filter_flag;
            UWORD32 u4_mask;
            WORD32 i;
            WORD32 numbytes_row;
            numbytes_row = (ps_sps->i2_pic_width_in_luma_samples + 63) / 64;
            pu1_pic_no_loop_filter_flag += (y0 / 8) * numbytes_row;
            pu1_pic_no_loop_filter_flag += (x0 / 64);

 /* Generate (cb_size / 8) number of 1s */
 /* i.e (log2_cb_size - 2) number of 1s */
            u4_mask = LSB_ONES((cb_size >> 3));
 for(i = 0; i < (cb_size / 8); i++)
 {
 *pu1_pic_no_loop_filter_flag |= (u4_mask << (((x0) / 8) % 8));
                pu1_pic_no_loop_filter_flag += numbytes_row;
 }
 }
 }

 {
        UWORD32 u4_skip_top = 0;
        UWORD32 u4_mask;
        UWORD32 u4_top_mask, u4_left_mask;
        UWORD32 u4_min_cu_x = x0 / 8;
        UWORD32 u4_min_cu_y = y0 / 8;

        pu4_skip_top += (u4_min_cu_x / 32);


 if(ps_slice_hdr->i1_slice_type != ISLICE)
 {
            WORD32 ctx_idx_inc;
            ctx_idx_inc = 0;

 if((0 != cu_pos_y) ||
 ((0 != ps_codec->s_parse.i4_ctb_slice_y) &&
 (0 != ps_codec->s_parse.i4_ctb_tile_y)))
 {
                u4_skip_top = *pu4_skip_top;
                u4_skip_top >>= (u4_min_cu_x % 32);
 if(u4_skip_top & 1)
                    ctx_idx_inc++;
 }

 /*****************************************************************/
 /* If cu_pos_x is non-zero then left is available                */
 /* If cu_pos_x is zero then ensure both the following are true   */
 /*    Current CTB is not the first CTB in a tile row             */
 /*    Current CTB is not the first CTB in a slice                */
 /*****************************************************************/
 if((0 != cu_pos_x) ||
 (((0 != ps_codec->s_parse.i4_ctb_slice_x) || (0 != ps_codec->s_parse.i4_ctb_slice_y)) &&
 (0 != ps_codec->s_parse.i4_ctb_tile_x)))
 {
                u4_skip_left >>= (u4_min_cu_y % 32);
 if(u4_skip_left & 1)
                    ctx_idx_inc++;
 }
            TRACE_CABAC_CTXT("cu_skip_flag", ps_cabac->u4_range, (IHEVC_CAB_SKIP_FLAG + ctx_idx_inc));
            skip_flag = ihevcd_cabac_decode_bin(ps_cabac,
                                                ps_bitstrm,
 (IHEVC_CAB_SKIP_FLAG + ctx_idx_inc));

            AEV_TRACE("cu_skip_flag", skip_flag, ps_cabac->u4_range);
 }
 else
            skip_flag = 0;

 /* Update top skip_flag */
        u4_skip_top = *pu4_skip_top;
 /* Since Max cb_size is 64, maximum of 8 bits will be set or reset */
 /* Also since Coding block will be within 64x64 grid, only 8bits within a WORD32
         * need to be updated. These 8 bits will not cross 8 bit boundaries
         */
        u4_mask = LSB_ONES(cb_size / 8);
        u4_top_mask = u4_mask << (u4_min_cu_x % 32);


 if(skip_flag)
 {
            u4_skip_top |= u4_top_mask;
 }
 else
 {
            u4_skip_top &= ~u4_top_mask;
 }
 *pu4_skip_top = u4_skip_top;

 /* Update left skip_flag */
        u4_skip_left = ps_codec->s_parse.u4_skip_cu_left;
        u4_mask = LSB_ONES(cb_size / 8);
        u4_left_mask = u4_mask << (u4_min_cu_y % 32);

 if(skip_flag)
 {
            u4_skip_left |= u4_left_mask;
 }
 else
 {
            u4_skip_left &= ~u4_left_mask;
 }
        ps_codec->s_parse.u4_skip_cu_left = u4_skip_left;
 }
    ps_codec->s_parse.i4_cu_pcm_flag = 0;

 if(skip_flag)
 {
        WORD32 ctb_x_base;
        WORD32 ctb_y_base;

        ctb_x_base = ps_codec->s_parse.i4_ctb_x << ps_sps->i1_log2_ctb_size;
        ctb_y_base = ps_codec->s_parse.i4_ctb_y << ps_sps->i1_log2_ctb_size;

        ps_tu->b1_cb_cbf = 0;
        ps_tu->b1_cr_cbf = 0;
        ps_tu->b1_y_cbf = 0;
        ps_tu->b4_pos_x = ((x0 - ctb_x_base) >> 2);
        ps_tu->b4_pos_y = ((y0 - ctb_y_base) >> 2);
        ps_tu->b1_transquant_bypass = 0;
        ps_tu->b3_size = (log2_cb_size - 2);
        ps_tu->b7_qp = ps_codec->s_parse.u4_qp;
        ps_tu->b3_chroma_intra_mode_idx = INTRA_PRED_CHROMA_IDX_NONE;
        ps_tu->b6_luma_intra_mode   = INTRA_PRED_NONE;

 /* Set the first TU in CU flag */
 {
 if((ps_codec->s_parse.s_cu.i4_pos_x << 3) == (ps_tu->b4_pos_x << 2) &&
 (ps_codec->s_parse.s_cu.i4_pos_y << 3) == (ps_tu->b4_pos_y << 2))
 {
                ps_tu->b1_first_tu_in_cu = 1;
 }
 else
 {
                ps_tu->b1_first_tu_in_cu = 0;
 }
 }

        ps_codec->s_parse.ps_tu++;
        ps_codec->s_parse.s_cu.i4_tu_cnt++;
        ps_codec->s_parse.i4_pic_tu_idx++;

        ps_codec->s_parse.s_cu.i4_pred_mode = PRED_MODE_SKIP;
        ps_codec->s_parse.s_cu.i4_part_mode = PART_2Nx2N;
 {
 pu_t *ps_pu = ps_codec->s_parse.ps_pu;
            ps_pu->b2_part_idx = 0;
            ihevcd_parse_prediction_unit(ps_codec, x0, y0, cb_size, cb_size);
            STATS_UPDATE_PU_SKIP_SIZE(ps_pu);
 }
 }
 else
 {
        WORD32 pred_mode;
        WORD32 part_mode;
        WORD32 intra_split_flag;
        WORD32 is_mincb;
        cb_size = (1 << log2_cb_size);
        is_mincb = (cb_size == (1 << ps_sps->i1_log2_min_coding_block_size));
        pcm_flag = 0;
 if(ps_slice_hdr->i1_slice_type != ISLICE)
 {
            TRACE_CABAC_CTXT("pred_mode_flag", ps_cabac->u4_range, IHEVC_CAB_PRED_MODE);
            pred_mode = ihevcd_cabac_decode_bin(ps_cabac,
                                                ps_bitstrm,
                                                IHEVC_CAB_PRED_MODE);

            AEV_TRACE("pred_mode_flag", pred_mode, ps_cabac->u4_range);
 }
 else
 {
            pred_mode = PRED_MODE_INTRA;
 }

 /* If current CU is intra then set corresponging bit in picture level intra map */
 if(PRED_MODE_INTRA == pred_mode)
 {
            UWORD8 *pu1_pic_intra_flag = ps_codec->s_parse.pu1_pic_intra_flag;
            UWORD32 u4_mask;
            WORD32 i;
            WORD32 numbytes_row;
            numbytes_row = (ps_sps->i2_pic_width_in_luma_samples + 63) / 64;
            pu1_pic_intra_flag += (y0 / 8) * numbytes_row;
            pu1_pic_intra_flag += (x0 / 64);

 /* Generate (cb_size / 8) number of 1s */
 /* i.e (log2_cb_size - 2) number of 1s */
            u4_mask = LSB_ONES((cb_size >> 3));
 for(i = 0; i < (cb_size / 8); i++)
 {
 *pu1_pic_intra_flag |= (u4_mask << (((x0) / 8) % 8));
                pu1_pic_intra_flag += numbytes_row;
 }
 }

        ps_codec->s_parse.s_cu.i4_pred_mode = pred_mode;
        intra_split_flag = 0;
 if((PRED_MODE_INTRA != pred_mode) ||
                        is_mincb)
 {
            UWORD32 bin;
 if(PRED_MODE_INTRA == pred_mode)
 {
                TRACE_CABAC_CTXT("part_mode", ps_cabac->u4_range, IHEVC_CAB_PART_MODE);
                bin = ihevcd_cabac_decode_bin(ps_cabac, ps_bitstrm, IHEVC_CAB_PART_MODE);
                part_mode = (bin) ? PART_2Nx2N : PART_NxN;
 }
 else
 {
                WORD32 amp_enabled = ps_sps->i1_amp_enabled_flag;

                UWORD32 u4_max_bin_cnt = 0;



 if(amp_enabled && !is_mincb)
 {
                    part_mode = ihevcd_parse_part_mode_amp(ps_cabac, ps_bitstrm);
 }
 else
 {
                    WORD32 ctxt_inc = IHEVC_CAB_PART_MODE;

                    u4_max_bin_cnt = 2;
 if((is_mincb) && (cb_size > 8))
 {
                        u4_max_bin_cnt++;
 }

                    part_mode = -1;
                    TRACE_CABAC_CTXT("part_mode", ps_cabac->u4_range, IHEVC_CAB_PART_MODE);
 do
 {
                        bin = ihevcd_cabac_decode_bin(ps_cabac, ps_bitstrm,
                                                      ctxt_inc++);
                        part_mode++;
 }while(--u4_max_bin_cnt && !bin);

 /* If the last bin was zero, then increment part mode by 1 */
 if(!bin)
                        part_mode++;
 }


 }

            AEV_TRACE("part_mode", part_mode, ps_cabac->u4_range);

 }
 else
 {
            part_mode = 0;
            intra_split_flag = 0;
 }
        ps_codec->s_parse.s_cu.i4_part_mode = part_mode;

 if((PRED_MODE_INTRA == ps_codec->s_parse.s_cu.i4_pred_mode) &&
 (PART_NxN == ps_codec->s_parse.s_cu.i4_part_mode))
 {
            intra_split_flag = 1;
 }
        ps_codec->s_parse.s_cu.i4_part_mode = part_mode;
        ps_codec->s_parse.s_cu.i4_intra_split_flag = intra_split_flag;
 if(pred_mode == PRED_MODE_INTRA)
 {
            ps_codec->s_parse.i4_cu_pcm_flag = 0;
            ihevcd_parse_coding_unit_intra(ps_codec, x0, y0, log2_cb_size);
            pcm_flag = ps_codec->s_parse.i4_cu_pcm_flag;

 }
 else
 {
 if(part_mode == PART_2Nx2N)
 {
 pu_t *ps_pu = ps_codec->s_parse.ps_pu;
                ihevcd_parse_prediction_unit(ps_codec, x0, y0, cb_size, cb_size);
                ps_pu->b2_part_idx = 0;
 }
 else if(part_mode == PART_2NxN)
 {
 pu_t *ps_pu = ps_codec->s_parse.ps_pu;

                ihevcd_parse_prediction_unit(ps_codec, x0, y0, cb_size, cb_size / 2);
                ps_pu->b2_part_idx = 0;

                ps_pu = ps_codec->s_parse.ps_pu;
                ihevcd_parse_prediction_unit(ps_codec, x0, y0 + (cb_size / 2), cb_size, cb_size / 2);

                ps_pu->b2_part_idx = 1;
 }
 else if(part_mode == PART_Nx2N)
 {
 pu_t *ps_pu = ps_codec->s_parse.ps_pu;
                ihevcd_parse_prediction_unit(ps_codec, x0, y0, cb_size / 2, cb_size);
                ps_pu->b2_part_idx = 0;
                ps_pu = ps_codec->s_parse.ps_pu;
                ihevcd_parse_prediction_unit(ps_codec, x0 + (cb_size / 2), y0, cb_size / 2, cb_size);

                ps_pu->b2_part_idx = 1;
 }
 else if(part_mode == PART_2NxnU)
 {
 pu_t *ps_pu = ps_codec->s_parse.ps_pu;
                ihevcd_parse_prediction_unit(ps_codec, x0, y0, cb_size, cb_size / 4);
                ps_pu->b2_part_idx = 0;
                ps_pu = ps_codec->s_parse.ps_pu;
                ihevcd_parse_prediction_unit(ps_codec, x0, y0 + (cb_size / 4), cb_size, cb_size * 3 / 4);

                ps_pu->b2_part_idx = 1;
 }
 else if(part_mode == PART_2NxnD)
 {
 pu_t *ps_pu = ps_codec->s_parse.ps_pu;
                ihevcd_parse_prediction_unit(ps_codec, x0, y0, cb_size, cb_size * 3 / 4);
                ps_pu->b2_part_idx = 0;
                ps_pu = ps_codec->s_parse.ps_pu;
                ihevcd_parse_prediction_unit(ps_codec, x0, y0 + (cb_size * 3 / 4), cb_size, cb_size / 4);

                ps_pu->b2_part_idx = 1;
 }
 else if(part_mode == PART_nLx2N)
 {
 pu_t *ps_pu = ps_codec->s_parse.ps_pu;
                ihevcd_parse_prediction_unit(ps_codec, x0, y0, cb_size / 4, cb_size);
                ps_pu->b2_part_idx = 0;
                ps_pu = ps_codec->s_parse.ps_pu;
                ihevcd_parse_prediction_unit(ps_codec, x0 + (cb_size / 4), y0, cb_size * 3 / 4, cb_size);

                ps_pu->b2_part_idx = 1;
 }
 else if(part_mode == PART_nRx2N)
 {
 pu_t *ps_pu = ps_codec->s_parse.ps_pu;
                ihevcd_parse_prediction_unit(ps_codec, x0, y0, cb_size * 3 / 4, cb_size);
                ps_pu->b2_part_idx = 0;
                ps_pu = ps_codec->s_parse.ps_pu;
                ihevcd_parse_prediction_unit(ps_codec, x0 + (cb_size * 3 / 4), y0, cb_size / 4, cb_size);
                ps_pu->b2_part_idx = 1;
 }
 else
 { /* PART_NxN */
 pu_t *ps_pu = ps_codec->s_parse.ps_pu;

                ihevcd_parse_prediction_unit(ps_codec, x0, y0, cb_size / 2, cb_size / 2);
                ps_pu->b2_part_idx = 0;
                ps_pu = ps_codec->s_parse.ps_pu;
                ihevcd_parse_prediction_unit(ps_codec, x0 + (cb_size / 2), y0, cb_size / 2, cb_size / 2);

                ps_pu->b2_part_idx = 1;
                ps_pu = ps_codec->s_parse.ps_pu;
                ihevcd_parse_prediction_unit(ps_codec, x0, y0 + (cb_size / 2), cb_size / 2, cb_size / 2);

                ps_pu->b2_part_idx = 2;
                ps_pu = ps_codec->s_parse.ps_pu;
                ihevcd_parse_prediction_unit(ps_codec, x0 + (cb_size / 2), y0 + (cb_size / 2), cb_size / 2, cb_size / 2);

                ps_pu->b2_part_idx = 3;
 }
 }

 if(!pcm_flag)
 {
            WORD32 no_residual_syntax_flag = 0;
 pu_t *ps_pu;
 /* Since ps_pu is incremented for each PU parsed, decrement by 1 to
             *  access last decoded PU
             */
            ps_pu = ps_codec->s_parse.ps_pu - 1;
 if((PRED_MODE_INTRA != pred_mode) &&
 (!((part_mode == PART_2Nx2N) && ps_pu->b1_merge_flag)))
 {

                TRACE_CABAC_CTXT("rqt_root_cbf", ps_cabac->u4_range, IHEVC_CAB_NORES_IDX);
                no_residual_syntax_flag = ihevcd_cabac_decode_bin(ps_cabac,
                                                                  ps_bitstrm,
                                                                  IHEVC_CAB_NORES_IDX);

                AEV_TRACE("rqt_root_cbf", no_residual_syntax_flag,
                          ps_cabac->u4_range);
 /* TODO: HACK FOR COMPLIANCE WITH HM REFERENCE DECODER */
 /*********************************************************/
 /* currently the HM decoder expects qtroot cbf instead of */
 /* no_residue_flag which has opposite meaning             */
 /* This will be fixed once the software / spec is fixed   */
 /*********************************************************/
                no_residual_syntax_flag = 1 - no_residual_syntax_flag;
 }

 if(!no_residual_syntax_flag)
 {

                ps_codec->s_parse.s_cu.i4_max_trafo_depth = (pred_mode == PRED_MODE_INTRA) ?
 (ps_sps->i1_max_transform_hierarchy_depth_intra + intra_split_flag) :
 (ps_sps->i1_max_transform_hierarchy_depth_inter);
                ret = ihevcd_parse_transform_tree(ps_codec, x0, y0, x0, y0,
                                                  log2_cb_size, 0, 0,
                                                  ps_codec->s_parse.s_cu.ai4_intra_luma_pred_mode[0]);
                RETURN_IF((IHEVCD_ERROR_T)IHEVCD_SUCCESS != ret, ret);
 }
 else
 {
                WORD32 ctb_x_base;
                WORD32 ctb_y_base;

                ctb_x_base = ps_codec->s_parse.i4_ctb_x << ps_sps->i1_log2_ctb_size;
                ctb_y_base = ps_codec->s_parse.i4_ctb_y << ps_sps->i1_log2_ctb_size;

                ps_tu = ps_codec->s_parse.ps_tu;
                ps_tu->b1_cb_cbf = 0;
                ps_tu->b1_cr_cbf = 0;
                ps_tu->b1_y_cbf = 0;
                ps_tu->b4_pos_x = ((x0 - ctb_x_base) >> 2);
                ps_tu->b4_pos_y = ((y0 - ctb_y_base) >> 2);
                ps_tu->b1_transquant_bypass = 0;
                ps_tu->b3_size = (log2_cb_size - 2);
                ps_tu->b7_qp = ps_codec->s_parse.u4_qp;
                ps_tu->b3_chroma_intra_mode_idx = INTRA_PRED_CHROMA_IDX_NONE;
                ps_tu->b6_luma_intra_mode   = ps_codec->s_parse.s_cu.ai4_intra_luma_pred_mode[0];

 /* Set the first TU in CU flag */
 {
 if((ps_codec->s_parse.s_cu.i4_pos_x << 3) == (ps_tu->b4_pos_x << 2) &&
 (ps_codec->s_parse.s_cu.i4_pos_y << 3) == (ps_tu->b4_pos_y << 2))
 {
                        ps_tu->b1_first_tu_in_cu = 1;
 }
 else
 {
                        ps_tu->b1_first_tu_in_cu = 0;
 }
 }
                ps_codec->s_parse.ps_tu++;
                ps_codec->s_parse.s_cu.i4_tu_cnt++;
                ps_codec->s_parse.i4_pic_tu_idx++;

 }
 }

 }




 return ret;
}

Project: Android

WORD32 ihevcd_parse_transform_tree(codec_t *ps_codec,
                                   WORD32 x0, WORD32 y0,
                                   WORD32 cu_x_base, WORD32 cu_y_base,
                                   WORD32 log2_trafo_size,
                                   WORD32 trafo_depth,
                                   WORD32 blk_idx,
                                   WORD32 intra_pred_mode)
{
    IHEVCD_ERROR_T ret = (IHEVCD_ERROR_T)IHEVCD_SUCCESS;
 sps_t *ps_sps;
 pps_t *ps_pps;
    WORD32 value;
    WORD32 x1, y1;
    WORD32 max_trafo_depth;

 bitstrm_t *ps_bitstrm = &ps_codec->s_parse.s_bitstrm;
    WORD32 intra_split_flag;
    WORD32 split_transform_flag;
    WORD32 ctxt_idx;
 cab_ctxt_t *ps_cabac = &ps_codec->s_parse.s_cabac;

    max_trafo_depth = ps_codec->s_parse.s_cu.i4_max_trafo_depth;
    ps_sps = ps_codec->s_parse.ps_sps;
    ps_pps = ps_codec->s_parse.ps_pps;
    intra_split_flag = ps_codec->s_parse.s_cu.i4_intra_split_flag;

 {
        split_transform_flag = 0;
 if((log2_trafo_size <= ps_sps->i1_log2_max_transform_block_size) &&
 (log2_trafo_size > ps_sps->i1_log2_min_transform_block_size) &&
 (trafo_depth < max_trafo_depth) &&
 !(intra_split_flag && (trafo_depth == 0)))
 {
 /* encode the split transform flag, context derived as per Table9-37 */
            ctxt_idx = IHEVC_CAB_SPLIT_TFM + (5 - log2_trafo_size);

            TRACE_CABAC_CTXT("split_transform_flag", ps_cabac->u4_range, ctxt_idx);
            split_transform_flag = ihevcd_cabac_decode_bin(ps_cabac, ps_bitstrm, ctxt_idx);
            AEV_TRACE("split_transform_flag", split_transform_flag,
                      ps_cabac->u4_range);

 }
 else
 {
            WORD32 inter_split_flag = 0;

 if((0 == ps_sps->i1_max_transform_hierarchy_depth_inter) &&
 (PRED_MODE_INTER == ps_codec->s_parse.s_cu.i4_pred_mode) &&
 (PART_2Nx2N != ps_codec->s_parse.s_cu.i4_part_mode) &&
 (0 == trafo_depth))
 {
                inter_split_flag = 1;
 }

 if((log2_trafo_size > ps_sps->i1_log2_max_transform_block_size) ||
 ((1 == intra_split_flag) && (0 == trafo_depth)) ||
 (1 == inter_split_flag))
 {
                split_transform_flag = 1;
 }
 }

 if(0 == trafo_depth)
 {
            ps_codec->s_parse.s_cu.ai1_cbf_cr[trafo_depth] = 0;
            ps_codec->s_parse.s_cu.ai1_cbf_cb[trafo_depth] = 0;
 }
 else
 {
            ps_codec->s_parse.s_cu.ai1_cbf_cb[trafo_depth] = ps_codec->s_parse.s_cu.ai1_cbf_cb[trafo_depth - 1];
            ps_codec->s_parse.s_cu.ai1_cbf_cr[trafo_depth] = ps_codec->s_parse.s_cu.ai1_cbf_cr[trafo_depth - 1];
 }
 if(trafo_depth == 0 || log2_trafo_size > 2)
 {
            ctxt_idx = IHEVC_CAB_CBCR_IDX + trafo_depth;
 /* CBF for Cb/Cr is sent only if the parent CBF for Cb/Cr is non-zero */
 if((trafo_depth == 0) || ps_codec->s_parse.s_cu.ai1_cbf_cb[trafo_depth - 1])
 {
                TRACE_CABAC_CTXT("cbf_cb", ps_cabac->u4_range, ctxt_idx);
                value = ihevcd_cabac_decode_bin(ps_cabac, ps_bitstrm, ctxt_idx);
                AEV_TRACE("cbf_cb", value, ps_cabac->u4_range);
                ps_codec->s_parse.s_cu.ai1_cbf_cb[trafo_depth] = value;
 }

 if((trafo_depth == 0) || ps_codec->s_parse.s_cu.ai1_cbf_cr[trafo_depth - 1])
 {
                TRACE_CABAC_CTXT("cbf_cr", ps_cabac->u4_range, ctxt_idx);
                value = ihevcd_cabac_decode_bin(ps_cabac, ps_bitstrm, ctxt_idx);
                AEV_TRACE("cbf_cr", value, ps_cabac->u4_range);
                ps_codec->s_parse.s_cu.ai1_cbf_cr[trafo_depth] = value;
 }
 }
 if(split_transform_flag)
 {
            WORD32 intra_pred_mode_tmp;
            x1 = x0 + ((1 << log2_trafo_size) >> 1);
            y1 = y0 + ((1 << log2_trafo_size) >> 1);

 /* For transform depth of zero, intra pred mode as decoded at CU */
 /* level is sent to the transform tree nodes */
 /* When depth is non-zero intra pred mode of parent node is sent */
 /* This takes care of passing correct mode to all the child nodes */
            intra_pred_mode_tmp = trafo_depth ? intra_pred_mode : ps_codec->s_parse.s_cu.ai4_intra_luma_pred_mode[0];
            ret = ihevcd_parse_transform_tree(ps_codec, x0, y0, x0, y0, log2_trafo_size - 1, trafo_depth + 1, 0, intra_pred_mode_tmp);
            RETURN_IF((IHEVCD_ERROR_T)IHEVCD_SUCCESS != ret, ret);

            intra_pred_mode_tmp = trafo_depth ? intra_pred_mode : ps_codec->s_parse.s_cu.ai4_intra_luma_pred_mode[1];
            ret = ihevcd_parse_transform_tree(ps_codec, x1, y0, x0, y0, log2_trafo_size - 1, trafo_depth + 1, 1, intra_pred_mode_tmp);
            RETURN_IF((IHEVCD_ERROR_T)IHEVCD_SUCCESS != ret, ret);

            intra_pred_mode_tmp = trafo_depth ? intra_pred_mode : ps_codec->s_parse.s_cu.ai4_intra_luma_pred_mode[2];
            ret = ihevcd_parse_transform_tree(ps_codec, x0, y1, x0, y0, log2_trafo_size - 1, trafo_depth + 1, 2, intra_pred_mode_tmp);
            RETURN_IF((IHEVCD_ERROR_T)IHEVCD_SUCCESS != ret, ret);

            intra_pred_mode_tmp = trafo_depth ? intra_pred_mode : ps_codec->s_parse.s_cu.ai4_intra_luma_pred_mode[3];
            ret = ihevcd_parse_transform_tree(ps_codec, x1, y1, x0, y0, log2_trafo_size - 1, trafo_depth + 1, 3, intra_pred_mode_tmp);
            RETURN_IF((IHEVCD_ERROR_T)IHEVCD_SUCCESS != ret, ret);

 }
 else
 {
            WORD32 ctb_x_base;
            WORD32 ctb_y_base;
            WORD32 cu_qp_delta_abs;



 tu_t *ps_tu = ps_codec->s_parse.ps_tu;
            cu_qp_delta_abs = 0;
            ctb_x_base = ps_codec->s_parse.i4_ctb_x << ps_sps->i1_log2_ctb_size;
            ctb_y_base = ps_codec->s_parse.i4_ctb_y << ps_sps->i1_log2_ctb_size;

 if((ps_codec->s_parse.s_cu.i4_pred_mode == PRED_MODE_INTRA) ||
 (trafo_depth != 0) ||
 (ps_codec->s_parse.s_cu.ai1_cbf_cb[trafo_depth]) ||
 (ps_codec->s_parse.s_cu.ai1_cbf_cr[trafo_depth]))
 {
                ctxt_idx = IHEVC_CAB_CBF_LUMA_IDX;
                ctxt_idx += (trafo_depth == 0) ? 1 : 0;

                TRACE_CABAC_CTXT("cbf_luma", ps_cabac->u4_range, ctxt_idx);
                value = ihevcd_cabac_decode_bin(ps_cabac, ps_bitstrm, ctxt_idx);
                AEV_TRACE("cbf_luma", value, ps_cabac->u4_range);

                ps_codec->s_parse.s_cu.i1_cbf_luma = value;
 }
 else
 {
                ps_codec->s_parse.s_cu.i1_cbf_luma = 1;
 }

 /* Initialize ps_tu to default values */
 /* If required change this to WORD32 packed write */
            ps_tu->b1_cb_cbf = 0;
            ps_tu->b1_cr_cbf = 0;
            ps_tu->b1_y_cbf = 0;
            ps_tu->b4_pos_x = ((x0 - ctb_x_base) >> 2);
            ps_tu->b4_pos_y = ((y0 - ctb_y_base) >> 2);
            ps_tu->b1_transquant_bypass = ps_codec->s_parse.s_cu.i4_cu_transquant_bypass;
            ps_tu->b3_size = (log2_trafo_size - 2);
            ps_tu->b7_qp = ps_codec->s_parse.u4_qp;

            ps_tu->b6_luma_intra_mode = intra_pred_mode;
            ps_tu->b3_chroma_intra_mode_idx = ps_codec->s_parse.s_cu.i4_intra_chroma_pred_mode_idx;

 /* Section:7.3.12  Transform unit syntax inlined here */
 if(ps_codec->s_parse.s_cu.i1_cbf_luma ||
                            ps_codec->s_parse.s_cu.ai1_cbf_cb[trafo_depth] ||
                            ps_codec->s_parse.s_cu.ai1_cbf_cr[trafo_depth])
 {
                WORD32 intra_pred_mode_chroma;
 if(ps_pps->i1_cu_qp_delta_enabled_flag && !ps_codec->s_parse.i4_is_cu_qp_delta_coded)
 {


                    WORD32 c_max        = TU_MAX_QP_DELTA_ABS;
                    WORD32 ctxt_inc     = IHEVC_CAB_QP_DELTA_ABS;
                    WORD32 ctxt_inc_max = CTXT_MAX_QP_DELTA_ABS;

                    TRACE_CABAC_CTXT("cu_qp_delta_abs", ps_cabac->u4_range, ctxt_inc);
 /* qp_delta_abs is coded as combination of tunary and eg0 code  */
 /* See Table 9-32 and Table 9-37 for details on cu_qp_delta_abs */
                    cu_qp_delta_abs = ihevcd_cabac_decode_bins_tunary(ps_cabac,
                                                                      ps_bitstrm,
                                                                      c_max,
                                                                      ctxt_inc,
 0,
                                                                      ctxt_inc_max);
 if(cu_qp_delta_abs >= c_max)
 {
                        value = ihevcd_cabac_decode_bypass_bins_egk(ps_cabac, ps_bitstrm, 0);
                        cu_qp_delta_abs += value;
 }
                    AEV_TRACE("cu_qp_delta_abs", cu_qp_delta_abs, ps_cabac->u4_range);

                    ps_codec->s_parse.i4_is_cu_qp_delta_coded = 1;


 if(cu_qp_delta_abs)
 {
                        value = ihevcd_cabac_decode_bypass_bin(ps_cabac, ps_bitstrm);
                        AEV_TRACE("cu_qp_delta_sign", value, ps_cabac->u4_range);

 if(value)
                            cu_qp_delta_abs = -cu_qp_delta_abs;

 }

 if (cu_qp_delta_abs < MIN_CU_QP_DELTA_ABS(ps_sps->i1_bit_depth_luma_minus8)
 || cu_qp_delta_abs > MAX_CU_QP_DELTA_ABS(ps_sps->i1_bit_depth_luma_minus8))
 {
 return IHEVCD_INVALID_PARAMETER;
 }

                    ps_codec->s_parse.s_cu.i4_cu_qp_delta = cu_qp_delta_abs;

 }

 if(ps_codec->s_parse.s_cu.i1_cbf_luma)
 {
                    ps_tu->b1_y_cbf = 1;
                    ihevcd_parse_residual_coding(ps_codec, x0, y0, log2_trafo_size, 0, intra_pred_mode);
 }

 if(4 == ps_codec->s_parse.s_cu.i4_intra_chroma_pred_mode_idx)
                    intra_pred_mode_chroma = ps_codec->s_parse.s_cu.ai4_intra_luma_pred_mode[0];
 else
 {
                    intra_pred_mode_chroma = gau1_intra_pred_chroma_modes[ps_codec->s_parse.s_cu.i4_intra_chroma_pred_mode_idx];

 if(intra_pred_mode_chroma ==
                                    ps_codec->s_parse.s_cu.ai4_intra_luma_pred_mode[0])
 {
                        intra_pred_mode_chroma = INTRA_ANGULAR(34);
 }

 }
 if(log2_trafo_size > 2)
 {
 if(ps_codec->s_parse.s_cu.ai1_cbf_cb[trafo_depth])
 {
                        ps_tu->b1_cb_cbf = 1;
                        ihevcd_parse_residual_coding(ps_codec, x0, y0, log2_trafo_size - 1, 1, intra_pred_mode_chroma);
 }

 if(ps_codec->s_parse.s_cu.ai1_cbf_cr[trafo_depth])
 {
                        ps_tu->b1_cr_cbf = 1;
                        ihevcd_parse_residual_coding(ps_codec, x0, y0, log2_trafo_size - 1, 2, intra_pred_mode_chroma);
 }
 }
 else if(blk_idx == 3)
 {
 if(ps_codec->s_parse.s_cu.ai1_cbf_cb[trafo_depth])
 {
                        ps_tu->b1_cb_cbf = 1;
                        ihevcd_parse_residual_coding(ps_codec, cu_x_base, cu_y_base, log2_trafo_size, 1, intra_pred_mode_chroma);
 }

 if(ps_codec->s_parse.s_cu.ai1_cbf_cr[trafo_depth])
 {
                        ps_tu->b1_cr_cbf = 1;
                        ihevcd_parse_residual_coding(ps_codec, cu_x_base, cu_y_base, log2_trafo_size, 2, intra_pred_mode_chroma);
 }
 }
 else
 {
                    ps_tu->b3_chroma_intra_mode_idx = INTRA_PRED_CHROMA_IDX_NONE;
 }
 }
 else
 {
 if((3 != blk_idx) && (2 == log2_trafo_size))
 {
                    ps_tu->b3_chroma_intra_mode_idx = INTRA_PRED_CHROMA_IDX_NONE;
 }
 }

 /* Set the first TU in CU flag */
 {
 if((ps_codec->s_parse.s_cu.i4_pos_x << 3) == (ps_tu->b4_pos_x << 2) &&
 (ps_codec->s_parse.s_cu.i4_pos_y << 3) == (ps_tu->b4_pos_y << 2))
 {
                    ps_tu->b1_first_tu_in_cu = 1;
 }
 else
 {
                    ps_tu->b1_first_tu_in_cu = 0;
 }
 }
            ps_codec->s_parse.ps_tu++;
            ps_codec->s_parse.s_cu.i4_tu_cnt++;
            ps_codec->s_parse.i4_pic_tu_idx++;
 }
 }
 return ret;
}