Home | History | Annotate | Download | only in encoder
      1 /******************************************************************************
      2  *
      3  * Copyright (C) 2018 The Android Open Source Project
      4  *
      5  * Licensed under the Apache License, Version 2.0 (the "License");
      6  * you may not use this file except in compliance with the License.
      7  * You may obtain a copy of the License at:
      8  *
      9  * http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  *
     17  *****************************************************************************
     18  * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
     19 */
     20 /*!
     21 ******************************************************************************
     22 * \file ihevce_common_utils.c
     23 *
     24 * \brief
     25 *    Contains definitions of common utility functions used across encoder
     26 *
     27 * \date
     28 *    18/09/2012
     29 *
     30 * \author
     31 *    ittiam
     32 *
     33 * List of Functions
     34 *  ihevce_copy_2d()
     35 *  ihevce_hbd_copy_2d()
     36 *  ihevce_2d_square_copy_luma()
     37 *  ihevce_wt_avg_2d()
     38 *  ihevce_itrans_recon_dc_compute()
     39 *  ihevce_itrans_recon_dc()
     40 *  ihevce_hbd_itrans_recon_dc()
     41 *  ihevce_truncate_16bit_data_to_8bit()
     42 *  ihevce_convert_16bit_recon_to_8bit()
     43 *  ihevce_convert_16bit_input_to_8bit()
     44 *  ihevce_find_num_clusters_of_identical_points_1D()
     45 *  ihevce_hbd_compute_ssd()
     46 *  ihevce_compare_pu_mv_t()
     47 *  ihevce_set_pred_buf_as_free()
     48 *  ihevce_get_free_pred_buf_indices()
     49 *  ihevce_scale_mv()
     50 *  ihevce_osal_alloc()
     51 *  ihevce_osal_free()
     52 *  ihevce_osal_init()
     53 *  ihevce_osal_delete()
     54 *  ihevce_sum_abs_seq()
     55 *  ihevce_ssd_calculator()
     56 *  ihevce_chroma_interleave_ssd_calculator()
     57 *  ihevce_ssd_and_sad_calculator()
     58 *  ihevce_chroma_interleave_2d_copy()
     59 *  ihevce_hbd_chroma_interleave_2d_copy()
     60 *  ihevce_hbd_chroma_interleave_ssd_calculator()
     61 *  ihevce_get_chroma_eo_sao_params()
     62 *  ihevce_get_chroma_eo_sao_params_hbd()
     63 *  ihevce_compute_area_of_valid_cus_in_ctb()
     64 *  ihevce_create_cuNode_children()
     65 *  ihevce_cu_tree_init()
     66 *
     67 ******************************************************************************
     68 */
     69 
     70 /*****************************************************************************/
     71 /* File Includes                                                             */
     72 /*****************************************************************************/
     73 
     74 /* System include files */
     75 #include <stdio.h>
     76 #include <stdlib.h>
     77 #include <assert.h>
     78 #include <string.h>
     79 
     80 /* User include files */
     81 #include "ihevc_typedefs.h"
     82 #include "itt_video_api.h"
     83 #include "ihevce_api.h"
     84 
     85 #include "rc_cntrl_param.h"
     86 #include "rc_frame_info_collector.h"
     87 #include "rc_look_ahead_params.h"
     88 
     89 #include "ihevc_defs.h"
     90 #include "ihevc_debug.h"
     91 #include "ihevc_structs.h"
     92 #include "ihevc_platform_macros.h"
     93 #include "ihevc_deblk.h"
     94 #include "ihevc_itrans_recon.h"
     95 #include "ihevc_chroma_itrans_recon.h"
     96 #include "ihevc_chroma_intra_pred.h"
     97 #include "ihevc_intra_pred.h"
     98 #include "ihevc_inter_pred.h"
     99 #include "ihevc_mem_fns.h"
    100 #include "ihevc_padding.h"
    101 #include "ihevc_weighted_pred.h"
    102 #include "ihevc_sao.h"
    103 #include "ihevc_resi_trans.h"
    104 #include "ihevc_quant_iquant_ssd.h"
    105 #include "ihevc_cabac_tables.h"
    106 
    107 #include "ihevce_defs.h"
    108 #include "ihevce_hle_interface.h"
    109 #include "ihevce_lap_enc_structs.h"
    110 #include "ihevce_multi_thrd_structs.h"
    111 #include "ihevce_me_common_defs.h"
    112 #include "ihevce_had_satd.h"
    113 #include "ihevce_error_codes.h"
    114 #include "ihevce_bitstream.h"
    115 #include "ihevce_cabac.h"
    116 #include "ihevce_rdoq_macros.h"
    117 #include "ihevce_function_selector.h"
    118 #include "ihevce_enc_structs.h"
    119 #include "ihevce_entropy_structs.h"
    120 #include "ihevce_cmn_utils_instr_set_router.h"
    121 #include "ihevce_enc_loop_structs.h"
    122 #include "ihevce_common_utils.h"
    123 #include "ihevce_global_tables.h"
    124 
    125 #include "cast_types.h"
    126 #include "osal.h"
    127 #include "osal_defaults.h"
    128 
    129 /*****************************************************************************/
    130 /* Function Definitions                                                      */
    131 /*****************************************************************************/
    132 
    133 /**
    134 ******************************************************************************
    135 *
    136 *  @brief Performs the 2D copy
    137 *
    138 *  @par   Description
    139 *  This routine Performs the 2D copy
    140 *
    141 *  @param[inout]   pu1_dst
    142 *  pointer to the destination buffer
    143 *
    144 *  @param[in]   dst_strd
    145 *  destination stride in terms of the size of input/output unit
    146 *
    147 *  @param[inout]   pu1_src
    148 *  pointer to the source buffer
    149 *
    150 *  @param[in]   src_strd
    151 *  source stride in terms of the size of input/output unit
    152 *
    153 *  @param[in]   blk_wd
    154 *  number of samples to copy in a row
    155 *
    156 *  @param[in]   blk_ht
    157 *  number of rows to copy
    158 *
    159 ******************************************************************************
    160 */
    161 void ihevce_copy_2d(
    162     UWORD8 *pu1_dst,
    163     WORD32 dst_stride,
    164     UWORD8 *pu1_src,
    165     WORD32 src_stride,
    166     WORD32 blk_wd,
    167     WORD32 blk_ht)
    168 {
    169     WORD32 i;
    170 
    171     for(i = 0; i < blk_ht; i++)
    172     {
    173         memcpy(pu1_dst, pu1_src, blk_wd);
    174         pu1_dst += dst_stride;
    175         pu1_src += src_stride;
    176     }
    177 }
    178 
    179 /**
    180 ******************************************************************************
    181 *
    182 *  @brief Performs the 2D copy of luma data
    183 *
    184 *  @par   Description
    185 *  This routine performs the 2D square copy of luma data
    186 *
    187 *  @param[inout]   p_dst
    188 *  pointer to the destination buffer
    189 *
    190 *  @param[in]   dst_strd
    191 *  destination stride in terms of the size of input/output unit
    192 *
    193 *  @param[inout]   p_src
    194 *  pointer to the source buffer
    195 *
    196 *  @param[in]   src_strd
    197 *  source stride in terms of the size of input/output unit
    198 *
    199 *  @param[in]   num_cols_to_copy
    200 *  number of units in a line to copy from src to dst buffer
    201 *  Assumption : num_cols_to_copy <= min (dst_strd, src_strd)
    202 *
    203 *  @param[in]   unit_size
    204 *  size of the unit in bytes
    205 *
    206 *  @return      none
    207 *
    208 *  Assumptions : num_cols_to_copy = num_lines_to_copy,
    209 *  num_lines_to_copy can have {4, 16, 32, 64}
    210 *
    211 ******************************************************************************
    212 */
    213 void ihevce_2d_square_copy_luma(
    214     void *p_dst,
    215     WORD32 dst_strd,
    216     void *p_src,
    217     WORD32 src_strd,
    218     WORD32 num_cols_to_copy,
    219     WORD32 unit_size)
    220 {
    221     UWORD8 *pu1_dst = (UWORD8 *)p_dst;
    222     UWORD8 *pu1_src = (UWORD8 *)p_src;
    223     WORD32 i;
    224 
    225     for(i = 0; i < num_cols_to_copy; i++)
    226     {
    227         memcpy(pu1_dst, pu1_src, (num_cols_to_copy * unit_size));
    228         pu1_dst += (dst_strd * unit_size);
    229         pu1_src += (src_strd * unit_size);
    230     }
    231 }
    232 
    233 /**
    234 ********************************************************************************
    235 *
    236 *  @brief  Weighted pred of 2 predictor buffers as per spec
    237 *
    238 *  @param[in] pu1_pred0 : Pred0 buffer
    239 *
    240 *  @param[in] pu1_pred1 : Pred1 buffer
    241 *
    242 *  @param[in] pred0_strd : Stride of pred0 buffer
    243 *
    244 *  @param[in] pred1_strd : Stride of pred1 buffer
    245 *
    246 *  @param[in] wd : Width of pred block
    247 *
    248 *  @param[in] ht : Height of pred block
    249 *
    250 *  @param[out] pu1_dst : Destination buffer that will hold result
    251 *
    252 *  @param[in] dst_strd : Stride of dest buffer
    253 *
    254 *  @param[in] w0 : Weighting factor of Pred0
    255 *
    256 *  @param[in] w1 : weighting factor of pred1
    257 *
    258 *  @param[in] o0 : offset for pred0
    259 *
    260 *  @param[in] o1 : offset for pred1
    261 *
    262 *  @param[in] log_wdc : shift factor as per spec
    263 *
    264 *  @return none
    265 *
    266 ********************************************************************************
    267 */
    268 void ihevce_wt_avg_2d(
    269     UWORD8 *pu1_pred0,
    270     UWORD8 *pu1_pred1,
    271     WORD32 pred0_strd,
    272     WORD32 pred1_strd,
    273     WORD32 wd,
    274     WORD32 ht,
    275     UWORD8 *pu1_dst,
    276     WORD32 dst_strd,
    277     WORD32 w0,
    278     WORD32 w1,
    279     WORD32 o0,
    280     WORD32 o1,
    281     WORD32 log_wdc)
    282 {
    283     /* Total Rounding term to be added, including offset */
    284     WORD32 rnd = (o0 + o1 + 1) >> 1;  // << log_wdc;
    285     /* Downshift */
    286     WORD32 shift = log_wdc + 1;
    287     /* loop counters */
    288     WORD32 i, j;
    289 
    290     /* Dst = ((w0*p0 + w1*p1) + ((o0 + o1 + 1) << logWDc)) >> (logWDc + 1) */
    291     /* In above formula, the additive term is constant and is evaluated    */
    292     /* outside loop and stored as "rnd".                                   */
    293     for(i = 0; i < ht; i++)
    294     {
    295         for(j = 0; j < wd; j++)
    296         {
    297             WORD32 tmp;
    298             tmp = IHEVCE_WT_PRED(pu1_pred0[j], pu1_pred1[j], w0, w1, rnd, shift);
    299             pu1_dst[j] = (UWORD8)(CLIP3(tmp, 0, 255));
    300         }
    301         pu1_pred0 += pred0_strd;
    302         pu1_pred1 += pred1_strd;
    303         pu1_dst += dst_strd;
    304     }
    305 }
    306 /**
    307 ******************************************************************************
    308 *
    309 *  @brief Performs the Recon for DC only coefficient case
    310 *
    311 *  @par   Description
    312 *  This routine performs the Recon for DC only coefficient case
    313 *
    314 *  @param[inout]   pu1_dst
    315 *  pointer to the destination buffer
    316 *
    317 *  @param[in]   pu1_pred
    318 *  pointer to the pred buffer
    319 *
    320 *  @param[in]   dst_strd
    321 *  destination stride
    322 *
    323 *  @param[in]   pred_strd
    324 *  pred buffer stride
    325 *
    326 *  @param[in]   trans_size
    327 *  transform size
    328 *
    329 * @param[in] col_mult
    330 *  chroma multiplier
    331 *
    332 *  @param[in]   dc_value
    333 *  residue value
    334 *
    335 *  @return      none
    336 *
    337 ******************************************************************************
    338 */
    339 static INLINE void ihevce_itrans_recon_dc_compute(
    340     UWORD8 *pu1_dst,
    341     UWORD8 *pu1_pred,
    342     WORD32 dst_strd,
    343     WORD32 pred_strd,
    344     WORD32 trans_size,
    345     WORD32 col_mult,
    346     WORD32 dc_value)
    347 {
    348     WORD32 row, col;
    349 
    350     for(row = 0; row < trans_size; row++)
    351     {
    352         for(col = 0; col < trans_size; col++)
    353         {
    354             pu1_dst[row * dst_strd + col * col_mult] =
    355                 CLIP_U8(pu1_pred[row * pred_strd + col * col_mult] + dc_value);
    356         }
    357     }
    358 }
    359 
    360 /**
    361 ******************************************************************************
    362 *
    363 *  @brief Performs the IQ+IT+Recon for DC only coefficient case
    364 *
    365 *  @par   Description
    366 *  This routine performs the IQ+IT+Recon for DC only coefficient case
    367 *
    368 *  @param[in]   pu1_pred
    369 *  pointer to the pred buffer
    370 *
    371 *  @param[in]   pred_strd
    372 *  pred buffer stride
    373 *
    374 *  @param[inout]   pu1_dst
    375 *  pointer to the destination buffer
    376 *
    377 *  @param[in]   dst_strd
    378 *  destination stride
    379 *
    380 *  @param[in]   trans_size
    381 *  transform size
    382 *
    383 * @param[in] i2_deq_value
    384 *  Dequant Coeffs
    385 *
    386 *  @param[in] chroma plane
    387 *  -1 : luma, 0 : chroma U, 1 : chroma V
    388 *
    389 *  @return      none
    390 *
    391 ******************************************************************************
    392 */
    393 void ihevce_itrans_recon_dc(
    394     UWORD8 *pu1_pred,
    395     WORD32 pred_strd,
    396     UWORD8 *pu1_dst,
    397     WORD32 dst_strd,
    398     WORD32 trans_size,
    399     WORD16 i2_deq_value,
    400     CHROMA_PLANE_ID_T e_chroma_plane)
    401 {
    402     WORD32 add, shift;
    403     WORD32 dc_value;
    404     UWORD8 *pu1_pred_tmp, *pu1_dst_tmp;
    405     WORD32 col_mult;
    406 
    407     assert(e_chroma_plane == NULL_PLANE || e_chroma_plane == U_PLANE || e_chroma_plane == V_PLANE);
    408     if(e_chroma_plane == NULL_PLANE)
    409     {
    410         pu1_pred_tmp = pu1_pred;
    411         pu1_dst_tmp = pu1_dst;
    412         col_mult = 1;
    413     }
    414     else
    415     {
    416         col_mult = 2;
    417         pu1_pred_tmp = pu1_pred + e_chroma_plane;
    418         pu1_dst_tmp = pu1_dst + e_chroma_plane;
    419     }
    420 
    421     shift = IT_SHIFT_STAGE_1;
    422     add = 1 << (shift - 1);
    423     dc_value = CLIP_S16((i2_deq_value * 64 + add) >> shift);
    424     shift = IT_SHIFT_STAGE_2;
    425     add = 1 << (shift - 1);
    426     dc_value = CLIP_S16((dc_value * 64 + add) >> shift);
    427     ihevce_itrans_recon_dc_compute(
    428         pu1_dst_tmp, pu1_pred_tmp, dst_strd, pred_strd, trans_size, col_mult, dc_value);
    429 }
    430 
    431 /*!
    432 ******************************************************************************
    433 * \if Function name : ihevce_find_num_clusters_of_identical_points_1D \endif
    434 *
    435 * \brief
    436 *
    437 *
    438 *****************************************************************************
    439 */
    440 WORD32 ihevce_find_num_clusters_of_identical_points_1D(
    441     UWORD8 *pu1_inp_array,
    442     UWORD8 *pu1_out_array,
    443     UWORD8 *pu1_freq_of_out_data_in_inp,
    444     WORD32 i4_num_inp_array_elements)
    445 {
    446     WORD32 i;
    447     UWORD8 u1_value = pu1_inp_array[0];
    448     WORD32 i4_num_clusters = i4_num_inp_array_elements;
    449     WORD32 i4_output_array_idx = 1;
    450 
    451     pu1_freq_of_out_data_in_inp[0] = 1;
    452     pu1_out_array[0] = u1_value;
    453 
    454     if(1 == i4_num_inp_array_elements)
    455     {
    456         return 1;
    457     }
    458 
    459     for(i = 1; i < i4_num_inp_array_elements; i++)
    460     {
    461         if(pu1_inp_array[i] == u1_value)
    462         {
    463             pu1_freq_of_out_data_in_inp[0]++;
    464             i4_num_clusters--;
    465         }
    466         else
    467         {
    468             pu1_out_array[i4_output_array_idx] = pu1_inp_array[i];
    469 
    470             i4_output_array_idx++;
    471         }
    472     }
    473 
    474     if(i4_num_clusters > 1)
    475     {
    476         WORD32 i4_num_sub_clusters;
    477 
    478         i4_num_sub_clusters = ihevce_find_num_clusters_of_identical_points_1D(
    479             &pu1_out_array[1],
    480             &pu1_out_array[1],
    481             &pu1_freq_of_out_data_in_inp[1],
    482             i4_num_clusters - 1);
    483 
    484         i4_num_clusters = 1 + i4_num_sub_clusters;
    485     }
    486 
    487     return i4_num_clusters;
    488 }
    489 
    490 /**
    491 *******************************************************************************
    492 *
    493 * @brief Compare Motion vectors function
    494 *
    495 * @par Description:
    496 *   Checks if MVs and Reference idx are excatly matching.
    497 *
    498 * @param[inout] ps_1
    499 *   motion vector 1 to be compared
    500 *
    501 * @param[in] ps_2
    502 *   motion vector 2 to be compared
    503 *
    504 * @returns
    505 *  0 : if not matching 1 : if matching
    506 *
    507 * @remarks
    508 *
    509 *******************************************************************************
    510 */
    511 WORD32 ihevce_compare_pu_mv_t(
    512     pu_mv_t *ps_pu_mv_1, pu_mv_t *ps_pu_mv_2, WORD32 i4_pred_mode_1, WORD32 i4_pred_mode_2)
    513 {
    514     WORD32 i4_l0_match, i4_l1_match;
    515     WORD32 i4_pred_l0, i4_pred_l1;
    516 
    517     i4_pred_l0 = (i4_pred_mode_1 != PRED_L1);
    518     i4_pred_l1 = (i4_pred_mode_1 != PRED_L0);
    519 
    520     if(i4_pred_mode_1 != i4_pred_mode_2)
    521         return 0;
    522 
    523     i4_l0_match = 0;
    524     i4_l1_match = 0;
    525 
    526     if(i4_pred_l0)
    527     {
    528         if(ps_pu_mv_1->i1_l0_ref_idx == ps_pu_mv_2->i1_l0_ref_idx)
    529         {
    530             if(0 == memcmp(&ps_pu_mv_1->s_l0_mv, &ps_pu_mv_2->s_l0_mv, sizeof(mv_t)))
    531                 i4_l0_match = 1;
    532         }
    533     }
    534     if(i4_pred_l1)
    535     {
    536         if(ps_pu_mv_1->i1_l1_ref_idx == ps_pu_mv_2->i1_l1_ref_idx)
    537         {
    538             if(0 == memcmp(&ps_pu_mv_1->s_l1_mv, &ps_pu_mv_2->s_l1_mv, sizeof(mv_t)))
    539                 i4_l1_match = 1;
    540         }
    541     }
    542 
    543     if(i4_pred_l0 && i4_pred_l1)
    544         return (i4_l0_match & i4_l1_match);
    545     else if(i4_pred_l0)
    546         return i4_l0_match;
    547     else
    548         return i4_l1_match;
    549 
    550 } /* End of ihevce_compare_pu_mv_t */
    551 
    552 /*!
    553 ******************************************************************************
    554 * \if Function name : ihevce_set_pred_buf_as_free \endif
    555 *
    556 * \brief
    557 *    Mark buffer as free
    558 *
    559 *****************************************************************************
    560 */
    561 void ihevce_set_pred_buf_as_free(UWORD32 *pu4_idx_array, UWORD8 u1_buf_id)
    562 {
    563     (*pu4_idx_array) &= ~(1 << u1_buf_id);
    564 }
    565 
    566 /*!
    567 ******************************************************************************
    568 * \if Function name : ihevce_get_free_pred_buf_indices \endif
    569 *
    570 * \brief
    571 *    get free buffer indices
    572 *
    573 *****************************************************************************
    574 */
    575 UWORD8 ihevce_get_free_pred_buf_indices(
    576     UWORD8 *pu1_idx_array, UWORD32 *pu4_bitfield, UWORD8 u1_num_bufs_requested)
    577 {
    578     UWORD8 i;
    579 
    580     UWORD8 u1_num_free_bufs_found = 0;
    581     UWORD32 u4_local_bitfield = *pu4_bitfield;
    582 
    583     ASSERT(u1_num_bufs_requested <= (32 - ihevce_num_ones_generic(u4_local_bitfield)));
    584 
    585     for(i = 0; u1_num_free_bufs_found < u1_num_bufs_requested; i++)
    586     {
    587         if(!(u4_local_bitfield & (1 << i)))
    588         {
    589             pu1_idx_array[u1_num_free_bufs_found++] = i;
    590             u4_local_bitfield |= (1 << i);
    591         }
    592     }
    593 
    594     (*pu4_bitfield) = u4_local_bitfield;
    595 
    596     return u1_num_free_bufs_found;
    597 }
    598 
    599 /*!
    600 ******************************************************************************
    601 * \if Function name : ihevce_scale_mv \endif
    602 *
    603 * \brief
    604 *    Scale mv basing on displacement of POC
    605 *
    606 *****************************************************************************
    607 */
    608 void ihevce_scale_mv(mv_t *ps_mv, WORD32 i4_poc_to, WORD32 i4_poc_from, WORD32 i4_curr_poc)
    609 {
    610     WORD32 td, tb, tx;
    611     WORD32 dist_scale_factor;
    612     WORD32 mvx, mvy;
    613 
    614     td = CLIP_S8(i4_curr_poc - i4_poc_from);
    615     tb = CLIP_S8(i4_curr_poc - i4_poc_to);
    616 
    617     tx = (16384 + (abs(td) >> 1)) / td;
    618 
    619     dist_scale_factor = (tb * tx + 32) >> 6;
    620     dist_scale_factor = CLIP3(dist_scale_factor, -4096, 4095);
    621 
    622     mvx = ps_mv->i2_mvx;
    623     mvy = ps_mv->i2_mvy;
    624 
    625     mvx = SIGN(dist_scale_factor * mvx) * ((abs(dist_scale_factor * mvx) + 127) >> 8);
    626     mvy = SIGN(dist_scale_factor * mvy) * ((abs(dist_scale_factor * mvy) + 127) >> 8);
    627 
    628     ps_mv->i2_mvx = CLIP_S16(mvx);
    629     ps_mv->i2_mvy = CLIP_S16(mvy);
    630 }
    631 
    632 /*!
    633 ******************************************************************************
    634 * \if Function name : ihevce_osal_alloc \endif
    635 *
    636 * \brief
    637 *    Memory allocate call back function passed to OSAL
    638 *
    639 * \param[in] pv_handle : handle to hle ctxt
    640 * \param[in] u4_size : size of memory required
    641 *
    642 * \return
    643 *    Memory pointer
    644 *
    645 * \author
    646 *  Ittiam
    647 *
    648 *****************************************************************************
    649 */
    650 void *ihevce_osal_alloc(void *pv_handle, UWORD32 u4_size)
    651 {
    652     ihevce_hle_ctxt_t *ps_hle_ctxt = (ihevce_hle_ctxt_t *)pv_handle;
    653     iv_mem_rec_t s_mem_tab;
    654 
    655     /* def init of memtab */
    656     s_mem_tab.i4_size = sizeof(iv_mem_rec_t);
    657     s_mem_tab.i4_mem_alignment = 8;
    658     s_mem_tab.e_mem_type = IV_EXT_CACHEABLE_NORMAL_MEM;
    659 
    660     /* allocate memory for required size */
    661     s_mem_tab.i4_mem_size = u4_size;
    662 
    663     ps_hle_ctxt->ihevce_mem_alloc(
    664         ps_hle_ctxt->pv_mem_mgr_hdl, &ps_hle_ctxt->ps_static_cfg_prms->s_sys_api, &s_mem_tab);
    665 
    666     return (s_mem_tab.pv_base);
    667 }
    668 
    669 /*!
    670 ******************************************************************************
    671 * \if Function name : ihevce_osal_free \endif
    672 *
    673 * \brief
    674 *    Memory free call back function passed to OSAL
    675 *
    676 * \param[in] pv_handle : handle to hle ctxt
    677 * \param[in] pv_mem : memory to be freed
    678 *
    679 * \return
    680 *    none
    681 *
    682 * \author
    683 *  Ittiam
    684 *
    685 *****************************************************************************
    686 */
    687 void ihevce_osal_free(void *pv_handle, void *pv_mem)
    688 {
    689     ihevce_hle_ctxt_t *ps_hle_ctxt = (ihevce_hle_ctxt_t *)pv_handle;
    690     iv_mem_rec_t s_mem_tab;
    691 
    692     /* def init of memtab */
    693     s_mem_tab.i4_size = sizeof(iv_mem_rec_t);
    694     s_mem_tab.i4_mem_alignment = 8;
    695     s_mem_tab.e_mem_type = IV_EXT_CACHEABLE_NORMAL_MEM;
    696 
    697     /* free memory */
    698     s_mem_tab.pv_base = pv_mem;
    699 
    700     ps_hle_ctxt->ihevce_mem_free(ps_hle_ctxt->pv_mem_mgr_hdl, &s_mem_tab);
    701 
    702     return;
    703 }
    704 
    705 /*!
    706 ******************************************************************************
    707 * \if Function name : ihevce_osal_init \endif
    708 *
    709 * \brief
    710 *    Function to initialise OSAL handle
    711 *
    712 * \return
    713 *    None
    714 *
    715 * \author
    716 *  Ittiam
    717 *
    718 *****************************************************************************
    719 */
    720 WORD32 ihevce_osal_init(void *pv_hle_ctxt)
    721 {
    722     /* local variables */
    723     ihevce_hle_ctxt_t *ps_hle_ctxt;
    724     osal_cb_funcs_t s_cb_funcs;
    725     WORD32 status = 0;
    726     void *pv_osal_handle;
    727     iv_mem_rec_t s_mem_tab;
    728 
    729     ps_hle_ctxt = (ihevce_hle_ctxt_t *)pv_hle_ctxt;
    730 
    731     /* def init of memtab */
    732     s_mem_tab.i4_size = sizeof(iv_mem_rec_t);
    733     s_mem_tab.i4_mem_alignment = 8;
    734     s_mem_tab.e_mem_type = IV_EXT_CACHEABLE_NORMAL_MEM;
    735 
    736     /* --------------------------------------------------------------------- */
    737     /*                      OSAL Hanndle create                              */
    738     /* --------------------------------------------------------------------- */
    739 
    740     /* Allocate memory for the handle */
    741     s_mem_tab.i4_mem_size = OSAL_HANDLE_SIZE;
    742 
    743     ps_hle_ctxt->ihevce_mem_alloc(
    744         ps_hle_ctxt->pv_mem_mgr_hdl, &ps_hle_ctxt->ps_static_cfg_prms->s_sys_api, &s_mem_tab);
    745     if(NULL == s_mem_tab.pv_base)
    746     {
    747         ps_hle_ctxt->ps_static_cfg_prms->s_sys_api.ihevce_printf(
    748             ps_hle_ctxt->ps_static_cfg_prms->s_sys_api.pv_cb_handle,
    749             "IHEVCE ERROR: Error in OSAL initialization\n");
    750         return (-1);
    751     }
    752 
    753     pv_osal_handle = s_mem_tab.pv_base;
    754 
    755     /* Initialize OSAL call back functions */
    756     s_cb_funcs.mmr_handle = (void *)ps_hle_ctxt;
    757     s_cb_funcs.osal_alloc = &ihevce_osal_alloc;
    758     s_cb_funcs.osal_free = &ihevce_osal_free;
    759 
    760     status = osal_init(pv_osal_handle);
    761     if(OSAL_SUCCESS != status)
    762     {
    763         ps_hle_ctxt->ps_static_cfg_prms->s_sys_api.ihevce_printf(
    764             ps_hle_ctxt->ps_static_cfg_prms->s_sys_api.pv_cb_handle,
    765             "IHEVCE ERROR: Error in OSAL initialization\n");
    766         return (-1);
    767     }
    768 
    769     status = osal_register_callbacks(pv_osal_handle, &s_cb_funcs);
    770     if(OSAL_SUCCESS != status)
    771     {
    772         ps_hle_ctxt->ps_static_cfg_prms->s_sys_api.ihevce_printf(
    773             ps_hle_ctxt->ps_static_cfg_prms->s_sys_api.pv_cb_handle,
    774             "IHEVCE ERROR: Error in OSAL initialization\n");
    775         return (-1);
    776     }
    777     ps_hle_ctxt->pv_osal_handle = pv_osal_handle;
    778 
    779     return (0);
    780 }
    781 
    782 /*!
    783 ******************************************************************************
    784 * \if Function name : ihevce_osal_delete \endif
    785 *
    786 * \brief
    787 *    Function to delete OSAL handle
    788 *
    789 * \return
    790 *    None
    791 *
    792 * \author
    793 *  Ittiam
    794 *
    795 *****************************************************************************
    796 */
    797 WORD32 ihevce_osal_delete(void *pv_hle_ctxt)
    798 {
    799     /* local variables */
    800     ihevce_hle_ctxt_t *ps_hle_ctxt;
    801     void *pv_osal_handle;
    802     iv_mem_rec_t s_mem_tab;
    803 
    804     ps_hle_ctxt = (ihevce_hle_ctxt_t *)pv_hle_ctxt;
    805     pv_osal_handle = ps_hle_ctxt->pv_osal_handle;
    806 
    807     /* def init of memtab */
    808     s_mem_tab.i4_size = sizeof(iv_mem_rec_t);
    809     s_mem_tab.i4_mem_alignment = 8;
    810     s_mem_tab.e_mem_type = IV_EXT_CACHEABLE_NORMAL_MEM;
    811 
    812     if(0 != osal_close(pv_osal_handle))
    813     {
    814         ps_hle_ctxt->ps_static_cfg_prms->s_sys_api.ihevce_printf(
    815             ps_hle_ctxt->ps_static_cfg_prms->s_sys_api.pv_cb_handle,
    816             "IHEVCE ERROR>> Unable to close OSAL\n");
    817         return (-1);
    818     }
    819 
    820     /* free osal handle */
    821     s_mem_tab.pv_base = pv_osal_handle;
    822 
    823     ps_hle_ctxt->ihevce_mem_free(ps_hle_ctxt->pv_mem_mgr_hdl, &s_mem_tab);
    824 
    825     return (0);
    826 }
    827 
    828 /**
    829 *******************************************************************************
    830 *
    831 * @brief
    832 *  Compute SSD between two blocks (8 bit input)
    833 *
    834 * @par Description:
    835 *
    836 * @param[in] pu1_inp
    837 *  UWORD8 pointer to the src block
    838 *
    839 * @param[in] pu1_ref
    840 *  UWORD8 pointer to the ref block
    841 *
    842 * @param[in] inp_stride
    843 *  UWORD32 Source stride
    844 *
    845 * @param[in] ref_stride
    846 *  UWORD32 ref stride
    847 *
    848 * @param[in] wd
    849 *  UWORD32 width of the block
    850 *
    851 * @param[in] ht
    852 *  UWORD32 height of the block
    853 *
    854 * @returns SSD
    855 *
    856 * @remarks none
    857 *
    858 *******************************************************************************
    859 */
    860 LWORD64 ihevce_ssd_calculator(
    861     UWORD8 *pu1_inp, UWORD8 *pu1_ref, UWORD32 inp_stride, UWORD32 ref_stride, UWORD32 wd, UWORD32 ht)
    862 {
    863     UWORD32 i, j;
    864     LWORD64 ssd = 0;
    865 
    866     for(i = 0; i < ht; i++)
    867     {
    868         for(j = 0; j < wd; j++)
    869         {
    870             ssd += (pu1_inp[j] - pu1_ref[j]) * (pu1_inp[j] - pu1_ref[j]);
    871         }
    872 
    873         pu1_inp += inp_stride;
    874         pu1_ref += ref_stride;
    875     }
    876 
    877     return ssd;
    878 }
    879 
    880 /**
    881 *******************************************************************************
    882 *
    883 * @brief
    884 *  Compute SSD between two blocks (8 bit input, chroma interleaved input)
    885 *
    886 * @par Description:
    887 *
    888 * @param[in] pu1_inp
    889 *  UWORD8 pointer to the src block
    890 *
    891 * @param[in] pu1_ref
    892 *  UWORD8 pointer to the ref block
    893 *
    894 * @param[in] inp_stride
    895 *  UWORD32 Source stride
    896 *
    897 * @param[in] ref_stride
    898 *  UWORD32 ref stride
    899 *
    900 * @param[in] wd
    901 *  UWORD32 width of the block
    902 *
    903 * @param[in] ht
    904 *  UWORD32 height of the block
    905 *
    906 * @returns SSD
    907 *
    908 * @remarks none
    909 *
    910 *******************************************************************************
    911 */
    912 LWORD64 ihevce_chroma_interleave_ssd_calculator(
    913     UWORD8 *pu1_inp, UWORD8 *pu1_ref, UWORD32 inp_stride, UWORD32 ref_stride, UWORD32 wd, UWORD32 ht)
    914 {
    915     UWORD32 i, j;
    916     LWORD64 ssd = 0;
    917 
    918     /* run a loop and find the ssd by doing diff followed by square */
    919     for(i = 0; i < ht; i++)
    920     {
    921         for(j = 0; j < wd; j++)
    922         {
    923             WORD32 val;
    924 
    925             /* note that chroma is interleaved */
    926             val = pu1_inp[j * 2] - pu1_ref[j * 2];
    927             ssd += val * val;
    928         }
    929         /* row level update */
    930         pu1_inp += inp_stride;
    931         pu1_ref += ref_stride;
    932     }
    933 
    934     return (ssd);
    935 }
    936 
    937 /**
    938 *******************************************************************************
    939 *
    940 * @brief
    941 *  Compute SSD & SAD between two blocks (8 bit input)
    942 *
    943 * @par Description:
    944 *
    945 * @param[in] pu1_recon
    946 *  UWORD8 pointer to the block 1
    947 *
    948 * @param[in] recon_strd
    949 *  UWORD32 stride of block 1
    950 *
    951 * @param[in] pu1_src
    952 *  UWORD8 pointer to the block 2
    953 *
    954 * @param[in] src_strd
    955 *  UWORD32 stride of block 2
    956 *
    957 * @param[in] trans_size
    958 *  UWORD32 block wd/ht
    959 *
    960 * @param[out] *pu4_blk_sad
    961 *  UWORD32 block SAD
    962 *
    963 * @returns SSD
    964 *
    965 * @remarks none
    966 *
    967 *******************************************************************************
    968 */
    969 LWORD64 ihevce_ssd_and_sad_calculator(
    970     UWORD8 *pu1_recon,
    971     WORD32 recon_strd,
    972     UWORD8 *pu1_src,
    973     WORD32 src_strd,
    974     WORD32 trans_size,
    975     UWORD32 *pu4_blk_sad)
    976 {
    977     WORD32 i, j, sad = 0;
    978     LWORD64 ssd = 0;
    979 
    980     /* run a loop and find the ssd by doing diff followed by square */
    981     for(i = 0; i < trans_size; i++)
    982     {
    983         for(j = 0; j < trans_size; j++)
    984         {
    985             WORD32 val;
    986 
    987             val = *pu1_src++ - *pu1_recon++;
    988             ssd += val * val;
    989             sad += abs(val);
    990         }
    991         /* row level update */
    992         pu1_src += src_strd - trans_size;
    993         pu1_recon += recon_strd - trans_size;
    994     }
    995     *pu4_blk_sad = sad;
    996 
    997     /* The return value is of type WORD32 */
    998     ssd = CLIP3(ssd, 0, 0x7fffffff);
    999 
   1000     return (ssd);
   1001 }
   1002 
   1003 /*!
   1004 ******************************************************************************
   1005 * \if Function name : ihevce_chroma_interleave_2d_copy \endif
   1006 *
   1007 * \brief
   1008 *    This function copies one plane (u/v) of interleaved chroma buffer from
   1009 *    source to destination
   1010 ******************************************************************************
   1011 */
   1012 void ihevce_chroma_interleave_2d_copy(
   1013     UWORD8 *pu1_uv_src_bp,
   1014     WORD32 src_strd,
   1015     UWORD8 *pu1_uv_dst_bp,
   1016     WORD32 dst_strd,
   1017     WORD32 w,
   1018     WORD32 h,
   1019     CHROMA_PLANE_ID_T e_chroma_plane)
   1020 {
   1021     WORD32 i, j;
   1022 
   1023     UWORD8 *pu1_src = (U_PLANE == e_chroma_plane) ? pu1_uv_src_bp : pu1_uv_src_bp + 1;
   1024     UWORD8 *pu1_dst = (U_PLANE == e_chroma_plane) ? pu1_uv_dst_bp : pu1_uv_dst_bp + 1;
   1025 
   1026     for(i = 0; i < h; i++)
   1027     {
   1028         for(j = 0; j < w; j++)
   1029         {
   1030             /* note that chroma is interleaved */
   1031             pu1_dst[j * 2] = pu1_src[j * 2];
   1032         }
   1033 
   1034         /* row level update */
   1035         pu1_src += src_strd;
   1036         pu1_dst += dst_strd;
   1037     }
   1038 }
   1039 
   1040 /**
   1041 *******************************************************************************
   1042 *
   1043 * @brief
   1044 *     Gets edge offset params
   1045 *
   1046 * @par Description:
   1047 *     Given the ctb and sao angle this function will calculate accumulated
   1048 *     error between source and recon and the corresponding count for 4 edge
   1049 *     indexes one each for peak,valley, half peak and half valley.
   1050 *
   1051 * @param[in]
   1052 *   ps_sao_ctxt:   Pointer to SAO context
   1053 *   eo_sao_class: specifies edge offset class
   1054 *   pi4_acc_error_category: pointer to an array to store accumulated error between source and recon
   1055 *   pi4_category_count    : pointer to an array to store number of peaks,valleys,half peaks and half valleys.
   1056 * @returns
   1057 *
   1058 * @remarks
   1059 *  None
   1060 *
   1061 *******************************************************************************/
   1062 void ihevce_get_chroma_eo_sao_params(
   1063     void *pv_sao_ctxt,
   1064     WORD32 eo_sao_class,
   1065     WORD32 *pi4_acc_error_category,
   1066     WORD32 *pi4_category_count)
   1067 {
   1068     WORD32 row_start, row_end, col_start, col_end, row, col;
   1069     WORD32 row_offset = 0, col_offset = 0;
   1070     WORD32 a, b, c, pel_error, edgeidx;
   1071     sao_ctxt_t *ps_sao_ctxt = (sao_ctxt_t *)pv_sao_ctxt;
   1072 
   1073     row_start = 0;
   1074     row_end = ps_sao_ctxt->i4_sao_blk_ht >> 1;
   1075     col_start = 0;
   1076     col_end = ps_sao_ctxt->i4_sao_blk_wd;
   1077 
   1078     if((ps_sao_ctxt->i4_ctb_x == 0) && (eo_sao_class != SAO_EDGE_90_DEG))
   1079     {
   1080         col_start = 2;
   1081     }
   1082 
   1083     if(((ps_sao_ctxt->i4_ctb_x + 1) == ps_sao_ctxt->ps_sps->i2_pic_wd_in_ctb) &&
   1084        (eo_sao_class != SAO_EDGE_90_DEG))
   1085     {
   1086         col_end = ps_sao_ctxt->i4_sao_blk_wd - 2;
   1087     }
   1088 
   1089     if((ps_sao_ctxt->i4_ctb_y == 0) && (eo_sao_class != SAO_EDGE_0_DEG))
   1090     {
   1091         row_start = 1;
   1092     }
   1093 
   1094     if(((ps_sao_ctxt->i4_ctb_y + 1) == ps_sao_ctxt->ps_sps->i2_pic_ht_in_ctb) &&
   1095        (eo_sao_class != SAO_EDGE_0_DEG))
   1096     {
   1097         row_end = row_end - 1;  //ps_sao_ctxt->i4_sao_blk_ht - 1;
   1098     }
   1099 
   1100     if(eo_sao_class == SAO_EDGE_0_DEG)
   1101     {
   1102         row_offset = 0;
   1103         col_offset = 2;
   1104     }
   1105     else if(eo_sao_class == SAO_EDGE_90_DEG)
   1106     {
   1107         row_offset = 1;
   1108         col_offset = 0;
   1109     }
   1110     else if(eo_sao_class == SAO_EDGE_135_DEG)
   1111     {
   1112         row_offset = 1;
   1113         col_offset = 2;
   1114     }
   1115     else if(eo_sao_class == SAO_EDGE_45_DEG)
   1116     {
   1117         row_offset = 1;
   1118         col_offset = -2;
   1119     }
   1120 
   1121     for(row = row_start; row < row_end; row++)
   1122     {
   1123         for(col = col_start; col < col_end; col++)
   1124         {
   1125             c = ps_sao_ctxt
   1126                     ->pu1_cur_chroma_recon_buf[col + row * ps_sao_ctxt->i4_cur_chroma_recon_stride];
   1127             a = ps_sao_ctxt->pu1_cur_chroma_recon_buf
   1128                     [(col - col_offset) +
   1129                      (row - row_offset) * ps_sao_ctxt->i4_cur_chroma_recon_stride];
   1130             b = ps_sao_ctxt->pu1_cur_chroma_recon_buf
   1131                     [(col + col_offset) +
   1132                      (row + row_offset) * ps_sao_ctxt->i4_cur_chroma_recon_stride];
   1133             pel_error =
   1134                 ps_sao_ctxt
   1135                     ->pu1_cur_chroma_src_buf[col + row * ps_sao_ctxt->i4_cur_chroma_src_stride] -
   1136                 ps_sao_ctxt
   1137                     ->pu1_cur_chroma_recon_buf[col + row * ps_sao_ctxt->i4_cur_chroma_recon_stride];
   1138             edgeidx = 2 + SIGN(c - a) + SIGN(c - b);
   1139 
   1140             if(pel_error != 0)
   1141             {
   1142                 pi4_acc_error_category[edgeidx] += pel_error;
   1143                 pi4_category_count[edgeidx]++;
   1144             }
   1145         }
   1146     }
   1147 }
   1148 
   1149 /**
   1150 *******************************************************************************
   1151 *
   1152 * @brief
   1153 *     Gets edge offset params
   1154 *
   1155 * @par Description:
   1156 *     Given the ctb and sao angle this function will calculate accumulated
   1157 *     error between source and recon and the coresponding count for 4 edge
   1158 *     indexes one each for peak,valley, half peak and half valley.
   1159 *
   1160 * @param[in]
   1161 *   ps_sao_ctxt:   Pointer to SAO context
   1162 *   eo_sao_class: specifies edge offset class
   1163 *   pi4_acc_error_category: pointer to an array to store accumulated error between source and recon
   1164 *   pi4_category_count    : pointer to an array to store number of peaks,valleys,half peaks and half valleys.
   1165 * @returns
   1166 *
   1167 * @remarks
   1168 *  None
   1169 *
   1170 *******************************************************************************/
   1171 void ihevce_get_luma_eo_sao_params(
   1172     void *pv_sao_ctxt,
   1173     WORD32 eo_sao_class,
   1174     WORD32 *pi4_acc_error_category,
   1175     WORD32 *pi4_category_count)
   1176 {
   1177     WORD32 row_start, row_end, col_start, col_end, row, col;
   1178     WORD32 row_offset = 0, col_offset = 0;
   1179     WORD32 a, b, c, pel_error, edgeidx;
   1180     sao_ctxt_t *ps_sao_ctxt = (sao_ctxt_t *)pv_sao_ctxt;
   1181 
   1182     row_start = 0;
   1183     row_end = ps_sao_ctxt->i4_sao_blk_ht;
   1184     col_start = 0;
   1185     col_end = ps_sao_ctxt->i4_sao_blk_wd;
   1186 
   1187     if((ps_sao_ctxt->i4_ctb_x == 0) && (eo_sao_class != SAO_EDGE_90_DEG))
   1188     {
   1189         col_start = 1;
   1190     }
   1191 
   1192     if(((ps_sao_ctxt->i4_ctb_x + 1) == ps_sao_ctxt->ps_sps->i2_pic_wd_in_ctb) &&
   1193        (eo_sao_class != SAO_EDGE_90_DEG))
   1194     {
   1195         col_end = ps_sao_ctxt->i4_sao_blk_wd - 1;
   1196     }
   1197 
   1198     if((ps_sao_ctxt->i4_ctb_y == 0) && (eo_sao_class != SAO_EDGE_0_DEG))
   1199     {
   1200         row_start = 1;
   1201     }
   1202 
   1203     if(((ps_sao_ctxt->i4_ctb_y + 1) == ps_sao_ctxt->ps_sps->i2_pic_ht_in_ctb) &&
   1204        (eo_sao_class != SAO_EDGE_0_DEG))
   1205     {
   1206         row_end = ps_sao_ctxt->i4_sao_blk_ht - 1;
   1207     }
   1208 
   1209     if(eo_sao_class == SAO_EDGE_0_DEG)
   1210     {
   1211         row_offset = 0;
   1212         col_offset = 1;
   1213     }
   1214     else if(eo_sao_class == SAO_EDGE_90_DEG)
   1215     {
   1216         row_offset = 1;
   1217         col_offset = 0;
   1218     }
   1219     else if(eo_sao_class == SAO_EDGE_135_DEG)
   1220     {
   1221         row_offset = 1;
   1222         col_offset = 1;
   1223     }
   1224     else if(eo_sao_class == SAO_EDGE_45_DEG)
   1225     {
   1226         row_offset = 1;
   1227         col_offset = -1;
   1228     }
   1229 
   1230     for(row = row_start; row < row_end; row++)
   1231     {
   1232         for(col = col_start; col < col_end; col++)
   1233         {
   1234             c = ps_sao_ctxt
   1235                     ->pu1_cur_luma_recon_buf[col + row * ps_sao_ctxt->i4_cur_luma_recon_stride];
   1236             a = ps_sao_ctxt->pu1_cur_luma_recon_buf
   1237                     [(col - col_offset) +
   1238                      (row - row_offset) * ps_sao_ctxt->i4_cur_luma_recon_stride];
   1239             b = ps_sao_ctxt->pu1_cur_luma_recon_buf
   1240                     [(col + col_offset) +
   1241                      (row + row_offset) * ps_sao_ctxt->i4_cur_luma_recon_stride];
   1242             pel_error =
   1243                 ps_sao_ctxt->pu1_cur_luma_src_buf[col + row * ps_sao_ctxt->i4_cur_luma_src_stride] -
   1244                 ps_sao_ctxt
   1245                     ->pu1_cur_luma_recon_buf[col + row * ps_sao_ctxt->i4_cur_luma_recon_stride];
   1246             edgeidx = 2 + SIGN(c - a) + SIGN(c - b);
   1247 
   1248             if(pel_error != 0)
   1249             {
   1250                 pi4_acc_error_category[edgeidx] += pel_error;
   1251                 pi4_category_count[edgeidx]++;
   1252             }
   1253         }
   1254     }
   1255 }
   1256 
   1257 /*!
   1258 ******************************************************************************
   1259 * \if Function name : ihevce_compute_area_of_valid_cus_in_ctb \endif
   1260 *
   1261 * \brief
   1262 *
   1263 *
   1264 *****************************************************************************
   1265 */
   1266 WORD32 ihevce_compute_area_of_valid_cus_in_ctb(cur_ctb_cu_tree_t *ps_cu_tree)
   1267 {
   1268     WORD32 i4_area;
   1269 
   1270     if(NULL == ps_cu_tree)
   1271     {
   1272         return 0;
   1273     }
   1274 
   1275     if(ps_cu_tree->is_node_valid)
   1276     {
   1277         i4_area = ps_cu_tree->u1_cu_size * ps_cu_tree->u1_cu_size;
   1278     }
   1279     else
   1280     {
   1281         i4_area = ihevce_compute_area_of_valid_cus_in_ctb(ps_cu_tree->ps_child_node_tl) +
   1282                   ihevce_compute_area_of_valid_cus_in_ctb(ps_cu_tree->ps_child_node_tr) +
   1283                   ihevce_compute_area_of_valid_cus_in_ctb(ps_cu_tree->ps_child_node_bl) +
   1284                   ihevce_compute_area_of_valid_cus_in_ctb(ps_cu_tree->ps_child_node_br);
   1285     }
   1286 
   1287     return i4_area;
   1288 }
   1289 
   1290 /*!
   1291 ******************************************************************************
   1292 * \if Function name : ihevce_create_cuNode_children \endif
   1293 *
   1294 * \brief
   1295 *
   1296 *
   1297 *****************************************************************************
   1298 */
   1299 static WORD32 ihevce_create_cuNode_children(
   1300     cur_ctb_cu_tree_t *ps_cu_tree_root,
   1301     cur_ctb_cu_tree_t *ps_cu_tree_cur_node,
   1302     WORD32 nodes_already_created)
   1303 {
   1304     cur_ctb_cu_tree_t *ps_tl;
   1305     cur_ctb_cu_tree_t *ps_tr;
   1306     cur_ctb_cu_tree_t *ps_bl;
   1307     cur_ctb_cu_tree_t *ps_br;
   1308 
   1309     ps_tl = ps_cu_tree_root + nodes_already_created;
   1310     ps_tr = ps_tl + 1;
   1311     ps_bl = ps_tr + 1;
   1312     ps_br = ps_bl + 1;
   1313     /*
   1314     ps_tl = (ai4_child_node_enable[0]) ? ps_tl : NULL;
   1315     ps_tr = (ai4_child_node_enable[1]) ? ps_tr : NULL;
   1316     ps_bl = (ai4_child_node_enable[2]) ? ps_bl : NULL;
   1317     ps_br = (ai4_child_node_enable[3]) ? ps_br : NULL;
   1318     */
   1319     ps_cu_tree_cur_node->ps_child_node_tl = ps_tl;
   1320     ps_cu_tree_cur_node->ps_child_node_tr = ps_tr;
   1321     ps_cu_tree_cur_node->ps_child_node_bl = ps_bl;
   1322     ps_cu_tree_cur_node->ps_child_node_br = ps_br;
   1323 
   1324     return 4;
   1325 }
   1326 
   1327 /*!
   1328 ******************************************************************************
   1329 * \if Function name : ihevce_cu_tree_init \endif
   1330 *
   1331 * \brief
   1332 *
   1333 *
   1334 *****************************************************************************
   1335 */
   1336 void ihevce_cu_tree_init(
   1337     cur_ctb_cu_tree_t *ps_cu_tree,
   1338     cur_ctb_cu_tree_t *ps_cu_tree_root,
   1339     WORD32 *pi4_nodes_created_in_cu_tree,
   1340     WORD32 tree_depth,
   1341     CU_POS_T e_grandparent_blk_pos,
   1342     CU_POS_T e_parent_blk_pos,
   1343     CU_POS_T e_cur_blk_pos)
   1344 {
   1345     WORD32 cu_pos_x = 0;
   1346     WORD32 cu_pos_y = 0;
   1347     WORD32 cu_size = 0;
   1348 
   1349     WORD32 children_nodes_required = 1;
   1350     WORD32 node_validity = 0;
   1351 
   1352     switch(tree_depth)
   1353     {
   1354     case 0:
   1355     {
   1356         /* 64x64 block */
   1357         cu_size = 64;
   1358         cu_pos_x = 0;
   1359         cu_pos_y = 0;
   1360 
   1361         break;
   1362     }
   1363     case 1:
   1364     {
   1365         /* 32x32 block */
   1366         cu_size = 32;
   1367 
   1368         /* Explanation for logic below - */
   1369         /* * pos_x and pos_y are in units of 8x8 CU's */
   1370         /* * pos_x = 0 for TL and BL children */
   1371         /* * pos_x = 4 for TR and BR children */
   1372         /* * pos_y = 0 for TL and TR children */
   1373         /* * pos_y = 4 for BL and BR children */
   1374         cu_pos_x = (e_cur_blk_pos & 1) << 2;
   1375         cu_pos_y = (e_cur_blk_pos & 2) << 1;
   1376 
   1377         break;
   1378     }
   1379     case 2:
   1380     {
   1381         /* 16x16 block */
   1382         WORD32 cu_pos_x_parent;
   1383         WORD32 cu_pos_y_parent;
   1384 
   1385         cu_size = 16;
   1386 
   1387         /* Explanation for logic below - */
   1388         /* See similar explanation above */
   1389         cu_pos_x_parent = (e_parent_blk_pos & 1) << 2;
   1390         cu_pos_y_parent = (e_parent_blk_pos & 2) << 1;
   1391         cu_pos_x = cu_pos_x_parent + ((e_cur_blk_pos & 1) << 1);
   1392         cu_pos_y = cu_pos_y_parent + (e_cur_blk_pos & 2);
   1393 
   1394         break;
   1395     }
   1396     case 3:
   1397     {
   1398         /* 8x8 block */
   1399         WORD32 cu_pos_x_grandparent;
   1400         WORD32 cu_pos_y_grandparent;
   1401 
   1402         WORD32 cu_pos_x_parent;
   1403         WORD32 cu_pos_y_parent;
   1404 
   1405         cu_size = 8;
   1406 
   1407         cu_pos_x_grandparent = (e_grandparent_blk_pos & 1) << 2;
   1408         cu_pos_y_grandparent = (e_grandparent_blk_pos & 2) << 1;
   1409         cu_pos_x_parent = cu_pos_x_grandparent + ((e_parent_blk_pos & 1) << 1);
   1410         cu_pos_y_parent = cu_pos_y_grandparent + (e_parent_blk_pos & 2);
   1411         cu_pos_x = cu_pos_x_parent + (e_cur_blk_pos & 1);
   1412         cu_pos_y = cu_pos_y_parent + ((e_cur_blk_pos & 2) >> 1);
   1413 
   1414         children_nodes_required = 0;
   1415 
   1416         break;
   1417     }
   1418     }
   1419 
   1420     /* Fill the current cu_tree node */
   1421     CU_TREE_NODE_FILL(ps_cu_tree, node_validity, cu_pos_x, cu_pos_y, cu_size, 1);
   1422 
   1423     if(children_nodes_required)
   1424     {
   1425         tree_depth++;
   1426 
   1427         (*pi4_nodes_created_in_cu_tree) += ihevce_create_cuNode_children(
   1428             ps_cu_tree_root, ps_cu_tree, (*pi4_nodes_created_in_cu_tree));
   1429 
   1430         ihevce_cu_tree_init(
   1431             ps_cu_tree->ps_child_node_tl,
   1432             ps_cu_tree_root,
   1433             pi4_nodes_created_in_cu_tree,
   1434             tree_depth,
   1435             e_parent_blk_pos,
   1436             e_cur_blk_pos,
   1437             POS_TL);
   1438 
   1439         ihevce_cu_tree_init(
   1440             ps_cu_tree->ps_child_node_tr,
   1441             ps_cu_tree_root,
   1442             pi4_nodes_created_in_cu_tree,
   1443             tree_depth,
   1444             e_parent_blk_pos,
   1445             e_cur_blk_pos,
   1446             POS_TR);
   1447 
   1448         ihevce_cu_tree_init(
   1449             ps_cu_tree->ps_child_node_bl,
   1450             ps_cu_tree_root,
   1451             pi4_nodes_created_in_cu_tree,
   1452             tree_depth,
   1453             e_parent_blk_pos,
   1454             e_cur_blk_pos,
   1455             POS_BL);
   1456 
   1457         ihevce_cu_tree_init(
   1458             ps_cu_tree->ps_child_node_br,
   1459             ps_cu_tree_root,
   1460             pi4_nodes_created_in_cu_tree,
   1461             tree_depth,
   1462             e_parent_blk_pos,
   1463             e_cur_blk_pos,
   1464             POS_BR);
   1465     }
   1466     else
   1467     {
   1468         NULLIFY_THE_CHILDREN_NODES(ps_cu_tree);
   1469     }
   1470 }
   1471