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