| /****************************************************************************** |
| * |
| * Copyright (C) 2018 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at: |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| ***************************************************************************** |
| * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore |
| */ |
| |
| /** |
| ****************************************************************************** |
| * \file ihevce_tu_tree_selector.c |
| * |
| * \brief |
| * Functions that facilitate selection of optimal TU tree |
| * |
| * \date |
| * 20/04/2016 |
| * |
| * \author |
| * Ittiam |
| * |
| ****************************************************************************** |
| */ |
| |
| /*****************************************************************************/ |
| /* File Includes */ |
| /*****************************************************************************/ |
| /* System include files */ |
| #include <stdio.h> |
| #include <string.h> |
| #include <stdlib.h> |
| #include <assert.h> |
| #include <stdarg.h> |
| #include <math.h> |
| #include <limits.h> |
| |
| /* User include files */ |
| #include "ihevc_typedefs.h" |
| #include "itt_video_api.h" |
| #include "ihevce_api.h" |
| |
| #include "rc_cntrl_param.h" |
| #include "rc_frame_info_collector.h" |
| #include "rc_look_ahead_params.h" |
| |
| #include "ihevc_defs.h" |
| #include "ihevc_structs.h" |
| #include "ihevc_platform_macros.h" |
| #include "ihevc_deblk.h" |
| #include "ihevc_itrans_recon.h" |
| #include "ihevc_chroma_itrans_recon.h" |
| #include "ihevc_chroma_intra_pred.h" |
| #include "ihevc_intra_pred.h" |
| #include "ihevc_inter_pred.h" |
| #include "ihevc_mem_fns.h" |
| #include "ihevc_padding.h" |
| #include "ihevc_weighted_pred.h" |
| #include "ihevc_sao.h" |
| #include "ihevc_resi_trans.h" |
| #include "ihevc_quant_iquant_ssd.h" |
| #include "ihevc_cabac_tables.h" |
| |
| #include "ihevce_defs.h" |
| #include "ihevce_lap_enc_structs.h" |
| #include "ihevce_multi_thrd_structs.h" |
| #include "ihevce_me_common_defs.h" |
| #include "ihevce_had_satd.h" |
| #include "ihevce_error_codes.h" |
| #include "ihevce_bitstream.h" |
| #include "ihevce_cabac.h" |
| #include "ihevce_rdoq_macros.h" |
| #include "ihevce_function_selector.h" |
| #include "ihevce_enc_structs.h" |
| #include "ihevce_entropy_structs.h" |
| #include "ihevce_cmn_utils_instr_set_router.h" |
| #include "ihevce_enc_loop_structs.h" |
| #include "ihevce_enc_loop_utils.h" |
| #include "ihevce_tu_tree_selector.h" |
| |
| /*****************************************************************************/ |
| /* Function Definitions */ |
| /*****************************************************************************/ |
| |
| /*! |
| ****************************************************************************** |
| * \if Function name : ihevce_tu_tree_coverage_in_cu \endif |
| * |
| * \brief |
| * Determination of the area within the CU that is swept by the TU tree. |
| * Input : Pointer to a node of the TU tree |
| * Output : Area covered by the current TU or its children |
| * |
| ***************************************************************************** |
| */ |
| WORD32 ihevce_tu_tree_coverage_in_cu(tu_tree_node_t *ps_node) |
| { |
| WORD32 i4_tu_tree_area = 0; |
| |
| if(ps_node->u1_is_valid_node) |
| { |
| i4_tu_tree_area += ps_node->s_luma_data.u1_size * ps_node->s_luma_data.u1_size; |
| } |
| else |
| { |
| if(NULL != ps_node->ps_child_node_tl) |
| { |
| i4_tu_tree_area += ihevce_tu_tree_coverage_in_cu(ps_node->ps_child_node_tl); |
| } |
| |
| if(NULL != ps_node->ps_child_node_tr) |
| { |
| i4_tu_tree_area += ihevce_tu_tree_coverage_in_cu(ps_node->ps_child_node_tr); |
| } |
| |
| if(NULL != ps_node->ps_child_node_bl) |
| { |
| i4_tu_tree_area += ihevce_tu_tree_coverage_in_cu(ps_node->ps_child_node_bl); |
| } |
| |
| if(NULL != ps_node->ps_child_node_br) |
| { |
| i4_tu_tree_area += ihevce_tu_tree_coverage_in_cu(ps_node->ps_child_node_br); |
| } |
| } |
| |
| return i4_tu_tree_area; |
| } |
| |
| static void ihevce_tu_node_data_init( |
| tu_node_data_t *ps_tu_data, UWORD8 u1_size, UWORD8 u1_posx, UWORD8 u1_posy) |
| { |
| ps_tu_data->u1_size = u1_size; |
| ps_tu_data->i8_ssd = 0; |
| ps_tu_data->i8_cost = 0; |
| #if ENABLE_INTER_ZCU_COST |
| ps_tu_data->i8_not_coded_cost = 0; |
| #endif |
| ps_tu_data->u4_sad = 0; |
| ps_tu_data->i4_bits = 0; |
| ps_tu_data->i4_num_bytes_used_for_ecd = 0; |
| ps_tu_data->u1_cbf = 0; |
| ps_tu_data->u1_reconBufId = UCHAR_MAX; |
| ps_tu_data->u1_posx = u1_posx; |
| ps_tu_data->u1_posy = u1_posy; |
| } |
| |
| /*! |
| ****************************************************************************** |
| * \if Function name : ihevce_tu_node_init \endif |
| * |
| * \brief |
| * This function initialises all nodes of the TU tree from the root upto and |
| * including the nodes at the max tree depth. Only those nodes that lie |
| * within the (max + 1) and (min - 1) depths are set as valid. Everything |
| * else is invalid. The pointers to the children nodes of the leaf-most |
| * nodes in the tree are assigned NULL. |
| * Input : Pointer to root of the tree containing TU info. |
| * Output : The memory of this node and all its progeny shall be modified |
| * returns Number of nodes of the TU tree that have been modified |
| * |
| ***************************************************************************** |
| */ |
| static UWORD16 ihevce_tu_node_init( |
| tu_tree_node_t *ps_root, |
| UWORD8 u1_size, |
| UWORD8 u1_parent_posx, |
| UWORD8 u1_parent_posy, |
| UWORD8 u1_cur_depth, |
| UWORD8 u1_min_tree_depth, |
| UWORD8 u1_max_tree_depth, |
| UWORD8 u1_chroma_processing_enabled, |
| UWORD8 u1_is_422, |
| TU_POS_T e_tu_pos) |
| { |
| tu_tree_node_t *ps_node; |
| tu_tree_node_t *ps_childNodeTL; |
| tu_tree_node_t *ps_childNodeTR; |
| tu_tree_node_t *ps_childNodeBL; |
| tu_tree_node_t *ps_childNodeBR; |
| |
| UWORD8 u1_start_index_for_parent = 0; |
| UWORD8 u1_start_index_for_child = 0; |
| UWORD16 u2_parent_offset = 0; |
| UWORD16 u2_child_offset = 0; |
| UWORD8 u1_posx = 0; |
| UWORD8 u1_posy = 0; |
| |
| const UWORD8 u1_nxn_tu_node_start_index = 0; |
| const UWORD8 u1_nBye2xnBye2_tu_node_start_index = 1; |
| const UWORD8 u1_nBye4xnBye4_tu_node_start_index = 1 + 4; |
| const UWORD8 u1_nBye8xnBye8_tu_node_start_index = 1 + 4 + 16; |
| const UWORD8 u1_nBye16xnBye16_tu_node_start_index = 1 + 4 + 16 + 64; |
| UWORD16 u2_num_nodes_initialised = 0; |
| |
| ASSERT(u1_cur_depth <= u1_max_tree_depth); |
| ASSERT(u1_max_tree_depth >= u1_min_tree_depth); |
| |
| switch(e_tu_pos) |
| { |
| case POS_TL: |
| { |
| u1_posx = u1_parent_posx; |
| u1_posy = u1_parent_posy; |
| |
| break; |
| } |
| case POS_TR: |
| { |
| u1_posx = u1_parent_posx + u1_size; |
| u1_posy = u1_parent_posy; |
| |
| break; |
| } |
| case POS_BL: |
| { |
| u1_posx = u1_parent_posx; |
| u1_posy = u1_parent_posy + u1_size; |
| |
| break; |
| } |
| case POS_BR: |
| { |
| u1_posx = u1_parent_posx + u1_size; |
| u1_posy = u1_parent_posy + u1_size; |
| |
| break; |
| } |
| default: |
| { |
| /* Here be dragons */ |
| ASSERT(0); |
| } |
| } |
| |
| switch(u1_cur_depth) |
| { |
| case 0: |
| { |
| u1_start_index_for_parent = u1_nxn_tu_node_start_index; |
| u1_start_index_for_child = u1_nBye2xnBye2_tu_node_start_index; |
| |
| u2_parent_offset = 0; |
| u2_child_offset = 0; |
| |
| break; |
| } |
| case 1: |
| { |
| u1_start_index_for_parent = u1_nBye2xnBye2_tu_node_start_index; |
| u1_start_index_for_child = u1_nBye4xnBye4_tu_node_start_index; |
| |
| u2_parent_offset = e_tu_pos; |
| u2_child_offset = 4 * u1_posx / u1_size + 8 * u1_posy / u1_size; |
| |
| break; |
| } |
| case 2: |
| { |
| u1_start_index_for_parent = u1_nBye4xnBye4_tu_node_start_index; |
| u1_start_index_for_child = u1_nBye8xnBye8_tu_node_start_index; |
| |
| u2_parent_offset = 2 * u1_parent_posx / u1_size + 4 * u1_parent_posy / u1_size + e_tu_pos; |
| u2_child_offset = 4 * u1_posx / u1_size + 16 * u1_posy / u1_size; |
| |
| break; |
| } |
| case 3: |
| { |
| u1_start_index_for_parent = u1_nBye8xnBye8_tu_node_start_index; |
| u1_start_index_for_child = u1_nBye16xnBye16_tu_node_start_index; |
| |
| u2_parent_offset = 2 * u1_parent_posx / u1_size + 8 * u1_parent_posy / u1_size + e_tu_pos; |
| u2_child_offset = 4 * u1_posx / u1_size + 32 * u1_posy / u1_size; |
| |
| break; |
| } |
| case 4: |
| { |
| u1_start_index_for_parent = u1_nBye16xnBye16_tu_node_start_index; |
| u1_start_index_for_child = 0; |
| |
| u2_parent_offset = 2 * u1_parent_posx / u1_size + 16 * u1_parent_posy / u1_size + e_tu_pos; |
| u2_child_offset = 0; |
| |
| break; |
| } |
| default: |
| { |
| /* Here be dragons */ |
| ASSERT(0); |
| } |
| } |
| |
| ASSERT((u1_start_index_for_parent + u2_parent_offset) < (256 + 64 + 16 + 4 + 1)); |
| ASSERT((u1_start_index_for_child + u2_child_offset + POS_BR) < (256 + 64 + 16 + 4 + 1)); |
| |
| ps_node = ps_root + u1_start_index_for_parent + u2_parent_offset; |
| ps_childNodeTL = ps_root + u1_start_index_for_child + u2_child_offset + POS_TL; |
| ps_childNodeTR = ps_root + u1_start_index_for_child + u2_child_offset + POS_TR; |
| ps_childNodeBL = ps_root + u1_start_index_for_child + u2_child_offset + POS_BL; |
| ps_childNodeBR = ps_root + u1_start_index_for_child + u2_child_offset + POS_BR; |
| |
| ihevce_tu_node_data_init(&ps_node->s_luma_data, u1_size, u1_posx, u1_posy); |
| |
| if(u1_chroma_processing_enabled) |
| { |
| UWORD8 i; |
| |
| if(u1_size > 4) |
| { |
| for(i = 0; i < (u1_is_422 + 1); i++) |
| { |
| ihevce_tu_node_data_init( |
| &ps_node->as_cb_data[i], |
| u1_size / 2, |
| u1_posx / 2, |
| !u1_is_422 ? u1_posy / 2 : u1_posy + i * u1_size / 2); |
| |
| ihevce_tu_node_data_init( |
| &ps_node->as_cr_data[i], |
| u1_size / 2, |
| u1_posx / 2, |
| !u1_is_422 ? u1_posy / 2 : u1_posy + i * u1_size / 2); |
| } |
| } |
| else if(POS_TL == e_tu_pos) |
| { |
| for(i = 0; i < (u1_is_422 + 1); i++) |
| { |
| ihevce_tu_node_data_init( |
| &ps_node->as_cb_data[i], |
| u1_size, |
| u1_posx / 2, |
| !u1_is_422 ? u1_posy / 2 : u1_posy + i * u1_size); |
| |
| ihevce_tu_node_data_init( |
| &ps_node->as_cr_data[i], |
| u1_size, |
| u1_posx / 2, |
| !u1_is_422 ? u1_posy / 2 : u1_posy + i * u1_size); |
| } |
| } |
| else |
| { |
| for(i = 0; i < (u1_is_422 + 1); i++) |
| { |
| ihevce_tu_node_data_init( |
| &ps_node->as_cb_data[i], |
| u1_size / 2, |
| u1_posx / 2, |
| !u1_is_422 ? u1_posy / 2 : u1_posy + i * u1_size); |
| |
| ihevce_tu_node_data_init( |
| &ps_node->as_cr_data[i], |
| u1_size / 2, |
| u1_posx / 2, |
| !u1_is_422 ? u1_posy / 2 : u1_posy + i * u1_size); |
| } |
| } |
| } |
| |
| if((u1_cur_depth >= u1_min_tree_depth) && (u1_cur_depth <= u1_max_tree_depth)) |
| { |
| ps_node->u1_is_valid_node = 1; |
| } |
| else |
| { |
| ps_node->u1_is_valid_node = 0; |
| } |
| |
| u2_num_nodes_initialised++; |
| |
| if((u1_cur_depth < u1_max_tree_depth) && (u1_size > MIN_TU_SIZE)) |
| { |
| ps_node->ps_child_node_tl = ps_childNodeTL; |
| ps_node->ps_child_node_tr = ps_childNodeTR; |
| ps_node->ps_child_node_bl = ps_childNodeBL; |
| ps_node->ps_child_node_br = ps_childNodeBR; |
| |
| u2_num_nodes_initialised += ihevce_tu_node_init( |
| ps_root, |
| u1_size / 2, |
| ps_node->s_luma_data.u1_posx, |
| ps_node->s_luma_data.u1_posy, |
| u1_cur_depth + 1, |
| u1_min_tree_depth, |
| u1_max_tree_depth, |
| u1_chroma_processing_enabled, |
| u1_is_422, |
| POS_TL); |
| |
| u2_num_nodes_initialised += ihevce_tu_node_init( |
| ps_root, |
| u1_size / 2, |
| ps_node->s_luma_data.u1_posx, |
| ps_node->s_luma_data.u1_posy, |
| u1_cur_depth + 1, |
| u1_min_tree_depth, |
| u1_max_tree_depth, |
| u1_chroma_processing_enabled, |
| u1_is_422, |
| POS_TR); |
| |
| u2_num_nodes_initialised += ihevce_tu_node_init( |
| ps_root, |
| u1_size / 2, |
| ps_node->s_luma_data.u1_posx, |
| ps_node->s_luma_data.u1_posy, |
| u1_cur_depth + 1, |
| u1_min_tree_depth, |
| u1_max_tree_depth, |
| u1_chroma_processing_enabled, |
| u1_is_422, |
| POS_BL); |
| |
| u2_num_nodes_initialised += ihevce_tu_node_init( |
| ps_root, |
| u1_size / 2, |
| ps_node->s_luma_data.u1_posx, |
| ps_node->s_luma_data.u1_posy, |
| u1_cur_depth + 1, |
| u1_min_tree_depth, |
| u1_max_tree_depth, |
| u1_chroma_processing_enabled, |
| u1_is_422, |
| POS_BR); |
| } |
| else |
| { |
| ps_node->ps_child_node_tl = NULL; |
| ps_node->ps_child_node_tr = NULL; |
| ps_node->ps_child_node_bl = NULL; |
| ps_node->ps_child_node_br = NULL; |
| } |
| |
| return u2_num_nodes_initialised; |
| } |
| |
| /*! |
| ****************************************************************************** |
| * \if Function name : ihevce_tu_tree_init \endif |
| * |
| * \brief |
| * Initialises all relevant data within all nodes for a specified TU tree |
| * Input : Pointer to root of the tree containing TU info. |
| * Output : Returns the number of nodes initialised |
| * |
| ***************************************************************************** |
| */ |
| UWORD16 ihevce_tu_tree_init( |
| tu_tree_node_t *ps_root, |
| UWORD8 u1_cu_size, |
| UWORD8 u1_min_tree_depth, |
| UWORD8 u1_max_tree_depth, |
| UWORD8 u1_chroma_processing_enabled, |
| UWORD8 u1_is_422) |
| { |
| UWORD16 u2_num_nodes = 0; |
| |
| ASSERT(u1_max_tree_depth >= u1_min_tree_depth); |
| |
| u2_num_nodes += ihevce_tu_node_init( |
| ps_root, |
| u1_cu_size, |
| 0, |
| 0, |
| 0, |
| u1_min_tree_depth, |
| u1_max_tree_depth, |
| u1_chroma_processing_enabled, |
| u1_is_422, |
| POS_TL); |
| |
| return u2_num_nodes; |
| } |
| |
| /*! |
| ****************************************************************************** |
| * \if Function name : ihevce_cabac_bins2Bits_converter_and_state_updater \endif |
| * |
| * \brief |
| * cabac bin to bits converter |
| * Input : 1. Pointer to buffer which stores the current CABAC state. This |
| * buffer shall be modified by this function. 2. Index to the cabac state |
| * that corresponds to the bin. 3. bin value |
| * Output : Number of bits required to encode the bin |
| * |
| ***************************************************************************** |
| */ |
| static INLINE UWORD32 ihevce_cabac_bins2Bits_converter_and_state_updater( |
| UWORD8 *pu1_cabac_ctxt, UWORD8 u1_cabac_state_idx, UWORD8 u1_bin_value) |
| { |
| UWORD32 u4_bits = 0; |
| |
| u4_bits += gau2_ihevce_cabac_bin_to_bits[pu1_cabac_ctxt[u1_cabac_state_idx] ^ u1_bin_value]; |
| pu1_cabac_ctxt[u1_cabac_state_idx] = |
| gau1_ihevc_next_state[(pu1_cabac_ctxt[u1_cabac_state_idx] << 1) | u1_bin_value]; |
| |
| return u4_bits; |
| } |
| |
| static tu_tree_node_t * |
| ihevce_tu_node_parent_finder(tu_tree_node_t *ps_root, tu_tree_node_t *ps_leaf) |
| { |
| UWORD8 u1_depth_of_leaf; |
| |
| GETRANGE(u1_depth_of_leaf, ps_root->s_luma_data.u1_size / ps_leaf->s_luma_data.u1_size); |
| u1_depth_of_leaf--; |
| |
| if(0 == u1_depth_of_leaf) |
| { |
| return NULL; |
| } |
| else if(1 == u1_depth_of_leaf) |
| { |
| return ps_root; |
| } |
| else |
| { |
| UWORD8 u1_switch_conditional = |
| (ps_leaf->s_luma_data.u1_posx >= ps_root->ps_child_node_tl->s_luma_data.u1_size) + |
| (ps_leaf->s_luma_data.u1_posy >= ps_root->ps_child_node_tl->s_luma_data.u1_size) * 2; |
| |
| ASSERT(NULL != ps_root->ps_child_node_tl); |
| ASSERT(NULL != ps_root->ps_child_node_tr); |
| ASSERT(NULL != ps_root->ps_child_node_bl); |
| ASSERT(NULL != ps_root->ps_child_node_br); |
| |
| switch(u1_switch_conditional) |
| { |
| case 0: |
| { |
| return ihevce_tu_node_parent_finder(ps_root->ps_child_node_tl, ps_leaf); |
| } |
| case 1: |
| { |
| return ihevce_tu_node_parent_finder(ps_root->ps_child_node_tr, ps_leaf); |
| } |
| case 2: |
| { |
| return ihevce_tu_node_parent_finder(ps_root->ps_child_node_bl, ps_leaf); |
| } |
| case 3: |
| { |
| return ihevce_tu_node_parent_finder(ps_root->ps_child_node_br, ps_leaf); |
| } |
| } |
| } |
| |
| return NULL; |
| } |
| |
| /*! |
| ****************************************************************************** |
| * \if Function name : ihevce_compute_bits_for_TUSplit_and_cbf \endif |
| * |
| * \notes |
| * 1. This function ought to be called before the call to 'ihevce_tu_tree_selector' |
| * of children TU's in order to determine bits to encode splitFlag as 1. |
| * This should also be called at the end of 'ihevce_tu_processor' in order |
| * to determine bits required to encode cbf and splitFlag. |
| * 2. When 'ENABLE_TOP_DOWN_TU_RECURSION' = 0 and 'INCLUDE_CHROMA_DURING_TU_RECURSION' = 1, |
| * it shall be assumed that parent chroma cbf is 1. |
| * 3. When 'INCLUDE_CHROMA_DURING_TU_RECURSION' = 0, this function works as |
| * though no chroma related syntax was included in the HEVC syntax for coding |
| * the transform tree |
| * Input : 1. ps_root: Pointer to root of the tree containing TU info |
| * 2. ps_leaf: Pointer to current node of the TU tree |
| * 3. pu1_cabac_ctxt: Pointer to buffer which stores the current CABAC |
| * state. This buffer shall be modified by this function |
| * Output : Number of bits required to encode cbf and splitFlags |
| * |
| ***************************************************************************** |
| */ |
| static WORD32 ihevce_compute_bits_for_TUSplit_and_cbf( |
| tu_tree_node_t *ps_root, |
| tu_tree_node_t *ps_leaf, |
| UWORD8 *pu1_cabac_ctxt, |
| UWORD8 u1_max_tu_size, |
| UWORD8 u1_min_tu_size, |
| UWORD8 u1_cur_depth, |
| UWORD8 u1_max_depth, |
| UWORD8 u1_is_intra, |
| UWORD8 u1_is_intra_nxn_pu, |
| UWORD8 u1_chroma_processing_enabled, |
| UWORD8 u1_is_422) |
| { |
| UWORD8 u1_cabac_state_idx; |
| UWORD8 u1_log2_tu_size; |
| |
| UWORD32 u4_num_bits = 0; |
| UWORD8 u1_tu_size = ps_leaf->s_luma_data.u1_size; |
| |
| ASSERT(u1_min_tu_size >= MIN_TU_SIZE); |
| ASSERT(u1_min_tu_size <= u1_max_tu_size); |
| ASSERT(u1_max_tu_size <= MAX_TU_SIZE); |
| ASSERT(u1_tu_size >= MIN_TU_SIZE); |
| ASSERT(u1_tu_size <= MAX_TU_SIZE); |
| ASSERT(u1_cur_depth <= u1_max_depth); |
| |
| GETRANGE(u1_log2_tu_size, u1_tu_size); |
| |
| if((ps_root->s_luma_data.u1_size >> u1_cur_depth) == u1_tu_size) |
| { |
| if((u1_tu_size <= u1_max_tu_size) && (u1_tu_size > u1_min_tu_size) && |
| (u1_cur_depth < u1_max_depth) && !(u1_is_intra_nxn_pu && !u1_cur_depth)) |
| { |
| u1_cabac_state_idx = IHEVC_CAB_SPLIT_TFM + (5 - u1_log2_tu_size); |
| u4_num_bits += ihevce_cabac_bins2Bits_converter_and_state_updater( |
| pu1_cabac_ctxt, u1_cabac_state_idx, 0); |
| } |
| |
| if(u1_chroma_processing_enabled && (u1_tu_size > 4)) |
| { |
| tu_tree_node_t *ps_parent = ihevce_tu_node_parent_finder(ps_root, ps_leaf); |
| |
| u1_cabac_state_idx = IHEVC_CAB_CBCR_IDX + u1_cur_depth; |
| |
| if(!u1_cur_depth || ps_parent->as_cb_data[0].u1_cbf || ps_parent->as_cb_data[1].u1_cbf) |
| { |
| if(u1_is_422) |
| { |
| u4_num_bits += ihevce_cabac_bins2Bits_converter_and_state_updater( |
| pu1_cabac_ctxt, u1_cabac_state_idx, ps_leaf->as_cb_data[0].u1_cbf); |
| |
| u4_num_bits += ihevce_cabac_bins2Bits_converter_and_state_updater( |
| pu1_cabac_ctxt, u1_cabac_state_idx, ps_leaf->as_cb_data[1].u1_cbf); |
| } |
| else |
| { |
| u4_num_bits += ihevce_cabac_bins2Bits_converter_and_state_updater( |
| pu1_cabac_ctxt, u1_cabac_state_idx, ps_leaf->as_cb_data[0].u1_cbf); |
| } |
| } |
| |
| if(!u1_cur_depth || ps_parent->as_cr_data[0].u1_cbf || ps_parent->as_cr_data[1].u1_cbf) |
| { |
| if(u1_is_422) |
| { |
| u4_num_bits += ihevce_cabac_bins2Bits_converter_and_state_updater( |
| pu1_cabac_ctxt, u1_cabac_state_idx, ps_leaf->as_cr_data[0].u1_cbf); |
| |
| u4_num_bits += ihevce_cabac_bins2Bits_converter_and_state_updater( |
| pu1_cabac_ctxt, u1_cabac_state_idx, ps_leaf->as_cr_data[1].u1_cbf); |
| } |
| else |
| { |
| u4_num_bits += ihevce_cabac_bins2Bits_converter_and_state_updater( |
| pu1_cabac_ctxt, u1_cabac_state_idx, ps_leaf->as_cr_data[0].u1_cbf); |
| } |
| } |
| } |
| |
| if(u1_is_intra || u1_cur_depth) |
| { |
| u1_cabac_state_idx = IHEVC_CAB_CBF_LUMA_IDX + !u1_cur_depth; |
| u4_num_bits += ihevce_cabac_bins2Bits_converter_and_state_updater( |
| pu1_cabac_ctxt, u1_cabac_state_idx, ps_leaf->s_luma_data.u1_cbf); |
| } |
| } |
| else |
| { |
| if((u1_tu_size <= u1_max_tu_size) && (u1_tu_size > u1_min_tu_size) && |
| (u1_cur_depth < u1_max_depth) && !(u1_is_intra_nxn_pu && !u1_cur_depth)) |
| { |
| u1_cabac_state_idx = IHEVC_CAB_SPLIT_TFM + (5 - u1_log2_tu_size); |
| u4_num_bits += ihevce_cabac_bins2Bits_converter_and_state_updater( |
| pu1_cabac_ctxt, u1_cabac_state_idx, 1); |
| } |
| |
| if(u1_chroma_processing_enabled && (u1_tu_size > 4)) |
| { |
| tu_tree_node_t *ps_parent = ihevce_tu_node_parent_finder(ps_root, ps_leaf); |
| |
| u1_cabac_state_idx = IHEVC_CAB_CBCR_IDX + u1_cur_depth; |
| |
| if(!u1_cur_depth || ps_parent->as_cb_data[0].u1_cbf || ps_parent->as_cb_data[1].u1_cbf) |
| { |
| if(u1_is_422 && (8 == u1_tu_size)) |
| { |
| u4_num_bits += ihevce_cabac_bins2Bits_converter_and_state_updater( |
| pu1_cabac_ctxt, u1_cabac_state_idx, ps_leaf->as_cb_data[0].u1_cbf); |
| |
| u4_num_bits += ihevce_cabac_bins2Bits_converter_and_state_updater( |
| pu1_cabac_ctxt, u1_cabac_state_idx, ps_leaf->as_cb_data[1].u1_cbf); |
| } |
| else |
| { |
| u4_num_bits += ihevce_cabac_bins2Bits_converter_and_state_updater( |
| pu1_cabac_ctxt, |
| u1_cabac_state_idx, |
| ps_leaf->as_cb_data[0].u1_cbf || ps_leaf->as_cb_data[1].u1_cbf); |
| } |
| } |
| |
| if(!u1_cur_depth || ps_parent->as_cr_data[0].u1_cbf || ps_parent->as_cr_data[1].u1_cbf) |
| { |
| if(u1_is_422 && (8 == u1_tu_size)) |
| { |
| u4_num_bits += ihevce_cabac_bins2Bits_converter_and_state_updater( |
| pu1_cabac_ctxt, u1_cabac_state_idx, ps_leaf->as_cr_data[0].u1_cbf); |
| |
| u4_num_bits += ihevce_cabac_bins2Bits_converter_and_state_updater( |
| pu1_cabac_ctxt, u1_cabac_state_idx, ps_leaf->as_cr_data[1].u1_cbf); |
| } |
| else |
| { |
| u4_num_bits += ihevce_cabac_bins2Bits_converter_and_state_updater( |
| pu1_cabac_ctxt, |
| u1_cabac_state_idx, |
| ps_leaf->as_cr_data[0].u1_cbf || ps_leaf->as_cr_data[1].u1_cbf); |
| } |
| } |
| } |
| } |
| |
| return u4_num_bits; |
| } |
| |
| /*! |
| ****************************************************************************** |
| * \if Function name : ihevce_tu_processor \endif |
| * |
| * \notes |
| * Input : 1. ps_ctxt: Pointer to enc-loop's context. Parts of this structure |
| * shall be modified by this function. They include, au1_cu_csbf, |
| * i8_cu_not_coded_cost, ai2_scratch and s_rdoq_sbh_ctxt |
| * 2. ps_node: Pointer to current node of the TU tree. This struct |
| * shall be modified by this function |
| * 3. pv_src: Pointer to buffer which stores the source |
| * 4. pv_pred: Pointer to buffer which stores the pred |
| * 5. pv_recon: Pointer to buffer which stores the recon |
| * This buffer shall be modified by this function |
| * 6. pi2_deq_data: Pointer to buffer which stores the output of IQ. |
| * This buffer shall be modified by this function |
| * 7. pu1_ecd: Pointer to buffer which stores the data output by |
| * entropy coding. This buffer shall be modified by this function |
| * 8. pu1_cabac_ctxt: Pointer to buffer which stores the current CABAC |
| * state. This buffer shall be modified by this function |
| * Output : NA |
| * |
| ***************************************************************************** |
| */ |
| static void ihevce_tu_processor( |
| ihevce_enc_loop_ctxt_t *ps_ctxt, |
| tu_tree_node_t *ps_node, |
| buffer_data_for_tu_t *ps_buffer_data, |
| UWORD8 *pu1_cabac_ctxt, |
| WORD32 i4_pred_mode, |
| #if USE_NOISE_TERM_IN_ZERO_CODING_DECISION_ALGORITHMS |
| WORD32 i4_alpha_stim_multiplier, |
| UWORD8 u1_is_cu_noisy, |
| #endif |
| UWORD8 u1_chroma_processing_enabled, |
| UWORD8 u1_compute_spatial_ssd) |
| { |
| UWORD8 u1_is_recon_available; |
| |
| void *pv_src = ps_buffer_data->s_src_pred_rec_buf_luma.pv_src; |
| void *pv_pred = ps_buffer_data->s_src_pred_rec_buf_luma.pv_pred; |
| void *pv_recon = ps_buffer_data->s_src_pred_rec_buf_luma.pv_recon; |
| WORD16 *pi2_deq_data = ps_buffer_data->pi2_deq_data; |
| UWORD8 *pu1_ecd = ps_buffer_data->ppu1_ecd[0]; |
| WORD32 i4_src_stride = ps_buffer_data->s_src_pred_rec_buf_luma.i4_src_stride; |
| WORD32 i4_pred_stride = ps_buffer_data->s_src_pred_rec_buf_luma.i4_pred_stride; |
| WORD32 i4_recon_stride = ps_buffer_data->s_src_pred_rec_buf_luma.i4_recon_stride; |
| WORD32 i4_deq_data_stride = ps_buffer_data->i4_deq_data_stride; |
| UWORD8 u1_size = ps_node->s_luma_data.u1_size; |
| UWORD8 u1_posx = ps_node->s_luma_data.u1_posx; |
| UWORD8 u1_posy = ps_node->s_luma_data.u1_posy; |
| WORD32 trans_size = (64 == u1_size) ? 32 : u1_size; |
| UWORD8 u1_is_422 = (ps_ctxt->u1_chroma_array_type == 2); |
| |
| (void)pu1_cabac_ctxt; |
| { |
| pv_src = ((UWORD8 *)pv_src) + u1_posx + u1_posy * i4_src_stride; |
| pv_pred = ((UWORD8 *)pv_pred) + u1_posx + u1_posy * i4_pred_stride; |
| pv_recon = ((UWORD8 *)pv_recon) + u1_posx + u1_posy * i4_recon_stride; |
| } |
| |
| pi2_deq_data += u1_posx + u1_posy * i4_deq_data_stride; |
| |
| /*2 Multi- dimensinal array based on trans size of rounding factor to be added here */ |
| /* arrays are for rounding factor corr. to 0-1 decision and 1-2 decision */ |
| /* Currently the complete array will contain only single value*/ |
| /*The rounding factor is calculated with the formula |
| Deadzone val = (((R1 - R0) * (2^(-8/3)) * lamMod) + 1)/2 |
| rounding factor = (1 - DeadZone Val) |
| |
| Assumption: Cabac states of All the sub-blocks in the TU are considered independent |
| */ |
| if((ps_ctxt->i4_quant_rounding_level == TU_LEVEL_QUANT_ROUNDING) && |
| (ps_node->s_luma_data.u1_posx || ps_node->s_luma_data.u1_posy)) |
| { |
| double i4_lamda_modifier; |
| |
| if((BSLICE == ps_ctxt->i1_slice_type) && (ps_ctxt->i4_temporal_layer_id)) |
| { |
| i4_lamda_modifier = ps_ctxt->i4_lamda_modifier * |
| CLIP3((((double)(ps_ctxt->i4_cu_qp - 12)) / 6.0), 2.00, 4.00); |
| } |
| else |
| { |
| i4_lamda_modifier = ps_ctxt->i4_lamda_modifier; |
| } |
| if(ps_ctxt->i4_use_const_lamda_modifier) |
| { |
| if(ISLICE == ps_ctxt->i1_slice_type) |
| { |
| i4_lamda_modifier = ps_ctxt->f_i_pic_lamda_modifier; |
| } |
| else |
| { |
| i4_lamda_modifier = CONST_LAMDA_MOD_VAL; |
| } |
| } |
| ps_ctxt->pi4_quant_round_factor_tu_0_1[trans_size >> 3] = &ps_ctxt->i4_quant_round_tu[0][0]; |
| ps_ctxt->pi4_quant_round_factor_tu_1_2[trans_size >> 3] = &ps_ctxt->i4_quant_round_tu[1][0]; |
| |
| memset( |
| ps_ctxt->pi4_quant_round_factor_tu_0_1[trans_size >> 3], |
| 0, |
| trans_size * trans_size * sizeof(WORD32)); |
| memset( |
| ps_ctxt->pi4_quant_round_factor_tu_1_2[trans_size >> 3], |
| 0, |
| trans_size * trans_size * sizeof(WORD32)); |
| |
| ihevce_quant_rounding_factor_gen( |
| trans_size, |
| 1, |
| &ps_ctxt->s_rdopt_entropy_ctxt, |
| ps_ctxt->pi4_quant_round_factor_tu_0_1[trans_size >> 3], |
| ps_ctxt->pi4_quant_round_factor_tu_1_2[trans_size >> 3], |
| i4_lamda_modifier, |
| 1); |
| } |
| else |
| { |
| ps_ctxt->pi4_quant_round_factor_tu_0_1[trans_size >> 3] = |
| ps_ctxt->pi4_quant_round_factor_cu_ctb_0_1[trans_size >> 3]; |
| ps_ctxt->pi4_quant_round_factor_tu_1_2[trans_size >> 3] = |
| ps_ctxt->pi4_quant_round_factor_cu_ctb_1_2[trans_size >> 3]; |
| } |
| |
| #if ENABLE_INTER_ZCU_COST |
| ps_ctxt->i8_cu_not_coded_cost = 0; |
| #endif |
| |
| { |
| ps_node->s_luma_data.u1_cbf = ihevce_t_q_iq_ssd_scan_fxn( |
| ps_ctxt, |
| (UWORD8 *)pv_pred, |
| i4_pred_stride, |
| (UWORD8 *)pv_src, |
| i4_src_stride, |
| pi2_deq_data, |
| i4_deq_data_stride, |
| (UWORD8 *)pv_recon, |
| i4_recon_stride, |
| pu1_ecd, |
| ps_ctxt->au1_cu_csbf, |
| ps_ctxt->i4_cu_csbf_strd, |
| u1_size, |
| i4_pred_mode, |
| &ps_node->s_luma_data.i8_ssd, |
| &ps_node->s_luma_data.i4_num_bytes_used_for_ecd, |
| &ps_node->s_luma_data.i4_bits, |
| &ps_node->s_luma_data.u4_sad, |
| &ps_node->s_luma_data.i4_zero_col, |
| &ps_node->s_luma_data.i4_zero_row, |
| &u1_is_recon_available, |
| ps_ctxt->s_rdoq_sbh_ctxt.i4_perform_all_cand_rdoq, |
| ps_ctxt->s_rdoq_sbh_ctxt.i4_perform_all_cand_sbh, |
| #if USE_NOISE_TERM_IN_ZERO_CODING_DECISION_ALGORITHMS |
| i4_alpha_stim_multiplier, |
| u1_is_cu_noisy, |
| #endif |
| u1_compute_spatial_ssd ? SPATIAL_DOMAIN_SSD : FREQUENCY_DOMAIN_SSD, |
| 1); |
| } |
| |
| #if ENABLE_INTER_ZCU_COST |
| ps_node->s_luma_data.i8_not_coded_cost = ps_ctxt->i8_cu_not_coded_cost; |
| #endif |
| |
| if(u1_compute_spatial_ssd && u1_is_recon_available) |
| { |
| ps_node->s_luma_data.u1_reconBufId = 0; |
| } |
| else |
| { |
| ps_node->s_luma_data.u1_reconBufId = UCHAR_MAX; |
| } |
| |
| ps_node->s_luma_data.i8_cost = |
| ps_node->s_luma_data.i8_ssd + |
| COMPUTE_RATE_COST_CLIP30( |
| ps_node->s_luma_data.i4_bits, ps_ctxt->i8_cl_ssd_lambda_qf, LAMBDA_Q_SHIFT); |
| |
| pu1_ecd += ps_node->s_luma_data.i4_num_bytes_used_for_ecd; |
| |
| if(u1_chroma_processing_enabled && |
| ((!(u1_posx % 8) && !(u1_posy % 8) && (4 == u1_size)) || (u1_size > 4))) |
| { |
| UWORD8 i; |
| void *pv_chroma_src; |
| void *pv_chroma_pred; |
| void *pv_chroma_recon; |
| WORD16 *pi2_deq_data_chroma; |
| |
| WORD32 i4_chroma_src_stride = ps_buffer_data->s_src_pred_rec_buf_chroma.i4_src_stride; |
| WORD32 i4_chroma_pred_stride = ps_buffer_data->s_src_pred_rec_buf_chroma.i4_pred_stride; |
| WORD32 i4_chroma_recon_stride = ps_buffer_data->s_src_pred_rec_buf_chroma.i4_recon_stride; |
| WORD32 i4_deq_data_stride_chroma = ps_buffer_data->i4_deq_data_stride_chroma; |
| |
| /* SubTU loop */ |
| for(i = 0; i < u1_is_422 + 1; i++) |
| { |
| UWORD8 u1_chroma_size = ps_node->as_cb_data[i].u1_size; |
| UWORD8 u1_chroma_posx = ps_node->as_cb_data[i].u1_posx; |
| UWORD8 u1_chroma_posy = ps_node->as_cb_data[i].u1_posy; |
| |
| #if ENABLE_INTER_ZCU_COST |
| ps_ctxt->i8_cu_not_coded_cost = 0; |
| #endif |
| |
| pi2_deq_data_chroma = ps_buffer_data->pi2_deq_data_chroma + (u1_chroma_posx * 2) + |
| u1_chroma_posy * i4_deq_data_stride_chroma; |
| |
| { |
| pv_chroma_src = ((UWORD8 *)ps_buffer_data->s_src_pred_rec_buf_chroma.pv_src) + |
| (u1_chroma_posx * 2) + u1_chroma_posy * i4_chroma_src_stride; |
| pv_chroma_pred = ((UWORD8 *)ps_buffer_data->s_src_pred_rec_buf_chroma.pv_pred) + |
| (u1_chroma_posx * 2) + u1_chroma_posy * i4_chroma_pred_stride; |
| pv_chroma_recon = ((UWORD8 *)ps_buffer_data->s_src_pred_rec_buf_chroma.pv_recon) + |
| (u1_chroma_posx * 2) + u1_chroma_posy * i4_chroma_recon_stride; |
| |
| ps_node->as_cb_data[i].u1_cbf = ihevce_chroma_t_q_iq_ssd_scan_fxn( |
| ps_ctxt, |
| (UWORD8 *)pv_chroma_pred, |
| i4_chroma_pred_stride, |
| (UWORD8 *)pv_chroma_src, |
| i4_chroma_src_stride, |
| pi2_deq_data_chroma, |
| i4_deq_data_stride_chroma, |
| (UWORD8 *)pv_chroma_recon, |
| i4_chroma_recon_stride, |
| pu1_ecd, |
| ps_ctxt->au1_cu_csbf, |
| ps_ctxt->i4_cu_csbf_strd, |
| u1_chroma_size, |
| SCAN_DIAG_UPRIGHT, |
| 0, |
| &ps_node->as_cb_data[i].i4_num_bytes_used_for_ecd, |
| &ps_node->as_cb_data[i].i4_bits, |
| &ps_node->as_cb_data[i].i4_zero_col, |
| &ps_node->as_cb_data[i].i4_zero_row, |
| &u1_is_recon_available, |
| ps_ctxt->s_rdoq_sbh_ctxt.i4_perform_all_cand_rdoq, |
| ps_ctxt->s_rdoq_sbh_ctxt.i4_perform_all_cand_sbh, |
| &ps_node->as_cb_data[i].i8_ssd, |
| #if USE_NOISE_TERM_IN_ZERO_CODING_DECISION_ALGORITHMS |
| i4_alpha_stim_multiplier, |
| u1_is_cu_noisy, |
| #endif |
| i4_pred_mode == PRED_MODE_SKIP, |
| u1_compute_spatial_ssd ? SPATIAL_DOMAIN_SSD : FREQUENCY_DOMAIN_SSD, |
| U_PLANE); |
| } |
| |
| #if ENABLE_INTER_ZCU_COST |
| ps_node->as_cb_data[i].i8_not_coded_cost = ps_ctxt->i8_cu_not_coded_cost; |
| #endif |
| |
| if(u1_compute_spatial_ssd && u1_is_recon_available) |
| { |
| ps_node->as_cb_data[i].u1_reconBufId = 0; |
| } |
| else |
| { |
| ps_node->as_cb_data[i].u1_reconBufId = UCHAR_MAX; |
| } |
| |
| ps_node->as_cb_data[i].i8_cost = |
| ps_node->as_cb_data[i].i8_ssd + COMPUTE_RATE_COST_CLIP30( |
| ps_node->as_cb_data[i].i4_bits, |
| ps_ctxt->i8_cl_ssd_lambda_chroma_qf, |
| LAMBDA_Q_SHIFT); |
| |
| #if WEIGH_CHROMA_COST |
| ps_node->as_cb_data[i].i8_cost = |
| (ps_node->as_cb_data[i].i8_cost * ps_ctxt->u4_chroma_cost_weighing_factor + |
| (1 << (CHROMA_COST_WEIGHING_FACTOR_Q_SHIFT - 1))) >> |
| CHROMA_COST_WEIGHING_FACTOR_Q_SHIFT; |
| #endif |
| |
| pu1_ecd += ps_node->as_cb_data[i].i4_num_bytes_used_for_ecd; |
| } |
| |
| for(i = 0; i < u1_is_422 + 1; i++) |
| { |
| UWORD8 u1_chroma_size = ps_node->as_cr_data[i].u1_size; |
| UWORD8 u1_chroma_posx = ps_node->as_cr_data[i].u1_posx; |
| UWORD8 u1_chroma_posy = ps_node->as_cr_data[i].u1_posy; |
| |
| #if ENABLE_INTER_ZCU_COST |
| ps_ctxt->i8_cu_not_coded_cost = 0; |
| #endif |
| |
| pi2_deq_data_chroma = ps_buffer_data->pi2_deq_data_chroma + u1_chroma_size + |
| (u1_chroma_posx * 2) + u1_chroma_posy * i4_deq_data_stride_chroma; |
| |
| { |
| pv_chroma_src = ((UWORD8 *)ps_buffer_data->s_src_pred_rec_buf_chroma.pv_src) + |
| (u1_chroma_posx * 2) + u1_chroma_posy * i4_chroma_src_stride; |
| pv_chroma_pred = ((UWORD8 *)ps_buffer_data->s_src_pred_rec_buf_chroma.pv_pred) + |
| (u1_chroma_posx * 2) + u1_chroma_posy * i4_chroma_pred_stride; |
| pv_chroma_recon = ((UWORD8 *)ps_buffer_data->s_src_pred_rec_buf_chroma.pv_recon) + |
| (u1_chroma_posx * 2) + u1_chroma_posy * i4_chroma_recon_stride; |
| |
| ps_node->as_cr_data[i].u1_cbf = ihevce_chroma_t_q_iq_ssd_scan_fxn( |
| ps_ctxt, |
| (UWORD8 *)pv_chroma_pred, |
| i4_chroma_pred_stride, |
| (UWORD8 *)pv_chroma_src, |
| i4_chroma_src_stride, |
| pi2_deq_data_chroma, |
| i4_deq_data_stride_chroma, |
| (UWORD8 *)pv_chroma_recon, |
| i4_chroma_recon_stride, |
| pu1_ecd, |
| ps_ctxt->au1_cu_csbf, |
| ps_ctxt->i4_cu_csbf_strd, |
| u1_chroma_size, |
| SCAN_DIAG_UPRIGHT, |
| 0, |
| &ps_node->as_cr_data[i].i4_num_bytes_used_for_ecd, |
| &ps_node->as_cr_data[i].i4_bits, |
| &ps_node->as_cr_data[i].i4_zero_col, |
| &ps_node->as_cr_data[i].i4_zero_row, |
| &u1_is_recon_available, |
| ps_ctxt->s_rdoq_sbh_ctxt.i4_perform_all_cand_rdoq, |
| ps_ctxt->s_rdoq_sbh_ctxt.i4_perform_all_cand_sbh, |
| &ps_node->as_cr_data[i].i8_ssd, |
| #if USE_NOISE_TERM_IN_ZERO_CODING_DECISION_ALGORITHMS |
| i4_alpha_stim_multiplier, |
| u1_is_cu_noisy, |
| #endif |
| i4_pred_mode == PRED_MODE_SKIP, |
| u1_compute_spatial_ssd ? SPATIAL_DOMAIN_SSD : FREQUENCY_DOMAIN_SSD, |
| V_PLANE); |
| } |
| |
| #if ENABLE_INTER_ZCU_COST |
| ps_node->as_cr_data[i].i8_not_coded_cost = ps_ctxt->i8_cu_not_coded_cost; |
| #endif |
| |
| if(u1_compute_spatial_ssd && u1_is_recon_available) |
| { |
| ps_node->as_cr_data[i].u1_reconBufId = 0; |
| } |
| else |
| { |
| ps_node->as_cr_data[i].u1_reconBufId = UCHAR_MAX; |
| } |
| |
| ps_node->as_cr_data[i].i8_cost = |
| ps_node->as_cr_data[i].i8_ssd + COMPUTE_RATE_COST_CLIP30( |
| ps_node->as_cr_data[i].i4_bits, |
| ps_ctxt->i8_cl_ssd_lambda_chroma_qf, |
| LAMBDA_Q_SHIFT); |
| |
| #if WEIGH_CHROMA_COST |
| ps_node->as_cr_data[i].i8_cost = |
| (ps_node->as_cr_data[i].i8_cost * ps_ctxt->u4_chroma_cost_weighing_factor + |
| (1 << (CHROMA_COST_WEIGHING_FACTOR_Q_SHIFT - 1))) >> |
| CHROMA_COST_WEIGHING_FACTOR_Q_SHIFT; |
| #endif |
| |
| pu1_ecd += ps_node->as_cr_data[i].i4_num_bytes_used_for_ecd; |
| } |
| } |
| } |
| |
| static INLINE void ihevce_nbr_data_copier( |
| nbr_4x4_t *ps_nbr_data_buf, |
| WORD32 i4_nbr_data_buf_stride, |
| WORD32 i4_cu_qp, |
| UWORD8 u1_cbf, |
| WORD32 u1_posx, |
| UWORD8 u1_posy, |
| UWORD8 u1_size) |
| { |
| WORD32 i, j; |
| |
| UWORD8 u1_num_4x4_in_tu = u1_size / 4; |
| |
| ps_nbr_data_buf += ((u1_posx) / 4) + (u1_posy / 4) * i4_nbr_data_buf_stride; |
| |
| for(i = 0; i < u1_num_4x4_in_tu; i++) |
| { |
| for(j = 0; j < u1_num_4x4_in_tu; j++) |
| { |
| ps_nbr_data_buf[j].b8_qp = i4_cu_qp; |
| ps_nbr_data_buf[j].b1_y_cbf = u1_cbf; |
| } |
| |
| ps_nbr_data_buf += i4_nbr_data_buf_stride; |
| } |
| } |
| |
| static INLINE void ihevce_debriefer_when_parent_wins( |
| tu_tree_node_t *ps_node, |
| FT_COPY_2D *pf_copy_2d, |
| FT_CHROMA_INTERLEAVE_2D_COPY *pf_chroma_interleave_2d_copy, |
| nbr_4x4_t *ps_nbr_data_buf, |
| WORD16 *pi2_deq_data_src, |
| WORD16 *pi2_deq_data_dst, |
| WORD16 *pi2_deq_data_src_chroma, |
| WORD16 *pi2_deq_data_dst_chroma, |
| void *pv_recon_src, |
| void *pv_recon_dst, |
| void *pv_recon_src_chroma, |
| void *pv_recon_dst_chroma, |
| UWORD8 *pu1_cabac_ctxt_src, |
| UWORD8 *pu1_cabac_ctxt_dst, |
| UWORD8 *pu1_ecd_src, |
| UWORD8 *pu1_ecd_dst, |
| WORD32 i4_nbr_data_buf_stride, |
| WORD32 i4_deq_data_src_stride, |
| WORD32 i4_deq_data_dst_stride, |
| WORD32 i4_deq_data_src_stride_chroma, |
| WORD32 i4_deq_data_dst_stride_chroma, |
| WORD32 i4_recon_src_stride, |
| WORD32 i4_recon_dst_stride, |
| WORD32 i4_recon_src_stride_chroma, |
| WORD32 i4_recon_dst_stride_chroma, |
| WORD32 i4_cabac_state_table_size, |
| WORD32 i4_cu_qp, |
| UWORD8 u1_chroma_processing_enabled, |
| UWORD8 u1_is_422, |
| UWORD8 u1_is_hbd) |
| { |
| UWORD8 i; |
| |
| UWORD32 u4_num_ecd_bytes = 0; |
| |
| /* Y */ |
| { |
| UWORD8 u1_posx = ps_node->s_luma_data.u1_posx; |
| UWORD8 u1_posy = ps_node->s_luma_data.u1_posy; |
| UWORD8 *pu1_deq_data_dst = |
| (UWORD8 *)(pi2_deq_data_dst + u1_posx + u1_posy * i4_deq_data_dst_stride); |
| UWORD8 *pu1_deq_data_src = |
| (UWORD8 *)(pi2_deq_data_src + u1_posx + u1_posy * i4_deq_data_src_stride); |
| UWORD8 *pu1_recon_dst; |
| UWORD8 *pu1_recon_src; |
| |
| { |
| pu1_recon_dst = (((UWORD8 *)pv_recon_dst) + u1_posx + u1_posy * i4_recon_dst_stride); |
| pu1_recon_src = (((UWORD8 *)pv_recon_src) + u1_posx + u1_posy * i4_recon_src_stride); |
| } |
| u4_num_ecd_bytes += ps_node->s_luma_data.i4_num_bytes_used_for_ecd; |
| |
| if(ps_node->s_luma_data.u1_reconBufId != UCHAR_MAX) |
| { |
| pf_copy_2d( |
| pu1_recon_dst, |
| i4_recon_dst_stride * (u1_is_hbd + 1), |
| pu1_recon_src, |
| i4_recon_src_stride * (u1_is_hbd + 1), |
| ps_node->s_luma_data.u1_size * (u1_is_hbd + 1), |
| ps_node->s_luma_data.u1_size); |
| } |
| else if(ps_node->s_luma_data.u1_cbf) |
| { |
| pf_copy_2d( |
| pu1_deq_data_dst, |
| i4_deq_data_dst_stride * 2, |
| pu1_deq_data_src, |
| i4_deq_data_src_stride * 2, |
| ps_node->s_luma_data.u1_size * 2, |
| ps_node->s_luma_data.u1_size); |
| } |
| } |
| |
| /* Cb */ |
| if(u1_chroma_processing_enabled) |
| { |
| for(i = 0; i < u1_is_422 + 1; i++) |
| { |
| UWORD8 u1_posx = ps_node->as_cb_data[i].u1_posx; |
| UWORD8 u1_posy = ps_node->as_cb_data[i].u1_posy; |
| UWORD8 *pu1_deq_data_dst = |
| (UWORD8 |
| *)(pi2_deq_data_dst_chroma + (u1_posx * 2) + (u1_posy * i4_deq_data_dst_stride_chroma)); |
| UWORD8 *pu1_deq_data_src = |
| (UWORD8 |
| *)(pi2_deq_data_src_chroma + (u1_posx * 2) + (u1_posy * i4_deq_data_src_stride_chroma)); |
| UWORD8 *pu1_recon_dst; |
| UWORD8 *pu1_recon_src; |
| |
| { |
| pu1_recon_dst = |
| (((UWORD8 *)pv_recon_dst_chroma) + (u1_posx * 2) + |
| u1_posy * i4_recon_dst_stride_chroma); |
| pu1_recon_src = |
| (((UWORD8 *)pv_recon_src_chroma) + (u1_posx * 2) + |
| u1_posy * i4_recon_src_stride_chroma); |
| } |
| u4_num_ecd_bytes += ps_node->as_cb_data[i].i4_num_bytes_used_for_ecd; |
| |
| if(ps_node->as_cb_data[i].u1_reconBufId != UCHAR_MAX) |
| { |
| { |
| pf_chroma_interleave_2d_copy( |
| pu1_recon_src, |
| i4_recon_src_stride_chroma * (u1_is_hbd + 1), |
| pu1_recon_dst, |
| i4_recon_dst_stride_chroma * (u1_is_hbd + 1), |
| ps_node->as_cb_data[i].u1_size * (u1_is_hbd + 1), |
| ps_node->as_cb_data[i].u1_size, |
| U_PLANE); |
| } |
| } |
| else if(ps_node->as_cb_data[i].u1_cbf) |
| { |
| pf_copy_2d( |
| pu1_deq_data_dst, |
| i4_deq_data_dst_stride_chroma * 2, |
| pu1_deq_data_src, |
| i4_deq_data_src_stride_chroma * 2, |
| ps_node->as_cb_data[i].u1_size * 2, |
| ps_node->as_cb_data[i].u1_size); |
| } |
| } |
| |
| /* Cr */ |
| for(i = 0; i < u1_is_422 + 1; i++) |
| { |
| UWORD8 u1_posx = ps_node->as_cr_data[i].u1_posx; |
| UWORD8 u1_posy = ps_node->as_cr_data[i].u1_posy; |
| UWORD8 *pu1_deq_data_dst = |
| (UWORD8 |
| *)(pi2_deq_data_dst_chroma + ps_node->as_cr_data[i].u1_size + (u1_posx * 2) + (u1_posy * i4_deq_data_dst_stride_chroma)); |
| UWORD8 *pu1_deq_data_src = |
| (UWORD8 |
| *)(pi2_deq_data_src_chroma + ps_node->as_cr_data[i].u1_size + (u1_posx * 2) + (u1_posy * i4_deq_data_src_stride_chroma)); |
| UWORD8 *pu1_recon_dst; |
| UWORD8 *pu1_recon_src; |
| |
| { |
| pu1_recon_dst = |
| (((UWORD8 *)pv_recon_dst_chroma) + (u1_posx * 2) + |
| u1_posy * i4_recon_dst_stride_chroma); |
| pu1_recon_src = |
| (((UWORD8 *)pv_recon_src_chroma) + (u1_posx * 2) + |
| u1_posy * i4_recon_src_stride_chroma); |
| } |
| u4_num_ecd_bytes += ps_node->as_cr_data[i].i4_num_bytes_used_for_ecd; |
| |
| if(ps_node->as_cr_data[i].u1_reconBufId != UCHAR_MAX) |
| { |
| { |
| pf_chroma_interleave_2d_copy( |
| pu1_recon_src, |
| i4_recon_src_stride_chroma * (u1_is_hbd + 1), |
| pu1_recon_dst, |
| i4_recon_dst_stride_chroma * (u1_is_hbd + 1), |
| ps_node->as_cr_data[i].u1_size * (u1_is_hbd + 1), |
| ps_node->as_cr_data[i].u1_size, |
| V_PLANE); |
| } |
| } |
| else if(ps_node->as_cr_data[i].u1_cbf) |
| { |
| pf_copy_2d( |
| pu1_deq_data_dst, |
| i4_deq_data_dst_stride_chroma * 2, |
| pu1_deq_data_src, |
| i4_deq_data_src_stride_chroma * 2, |
| ps_node->as_cr_data[i].u1_size * 2, |
| ps_node->as_cr_data[i].u1_size); |
| } |
| } |
| } |
| |
| if(pu1_ecd_dst != pu1_ecd_src) |
| { |
| memmove(pu1_ecd_dst, pu1_ecd_src, u4_num_ecd_bytes); |
| } |
| |
| memcpy(pu1_cabac_ctxt_dst, pu1_cabac_ctxt_src, i4_cabac_state_table_size); |
| |
| ihevce_nbr_data_copier( |
| ps_nbr_data_buf, |
| i4_nbr_data_buf_stride, |
| i4_cu_qp, |
| ps_node->s_luma_data.u1_cbf, |
| ps_node->s_luma_data.u1_posx, |
| ps_node->s_luma_data.u1_posy, |
| ps_node->s_luma_data.u1_size); |
| |
| ps_node->ps_child_node_tl = NULL; |
| ps_node->ps_child_node_tr = NULL; |
| ps_node->ps_child_node_bl = NULL; |
| ps_node->ps_child_node_br = NULL; |
| } |
| |
| /*! |
| ****************************************************************************** |
| * \if Function name : ihevce_ecd_buffer_pointer_updater \endif |
| * |
| * \brief |
| * Updates ppu1_ecd with current pointer |
| * Output : Number of byte positions 'pu1_ecd_buf_ptr_at_t0' is incremented by |
| * |
| ***************************************************************************** |
| */ |
| static INLINE UWORD32 ihevce_ecd_buffer_pointer_updater( |
| tu_tree_node_t *ps_node, |
| UWORD8 **ppu1_ecd, |
| UWORD8 *pu1_ecd_buf_ptr_at_t0, |
| UWORD8 u1_parent_has_won, |
| UWORD8 u1_chroma_processing_enabled, |
| UWORD8 u1_is_422) |
| { |
| UWORD8 i; |
| |
| UWORD32 u4_num_bytes = 0; |
| |
| if(u1_parent_has_won) |
| { |
| u4_num_bytes += ps_node->s_luma_data.i4_num_bytes_used_for_ecd; |
| |
| if(u1_chroma_processing_enabled) |
| { |
| for(i = 0; i < u1_is_422 + 1; i++) |
| { |
| u4_num_bytes += ps_node->as_cb_data[i].i4_num_bytes_used_for_ecd; |
| u4_num_bytes += ps_node->as_cr_data[i].i4_num_bytes_used_for_ecd; |
| } |
| } |
| } |
| else |
| { |
| u4_num_bytes += ps_node->ps_child_node_tl->s_luma_data.i4_num_bytes_used_for_ecd; |
| u4_num_bytes += ps_node->ps_child_node_tr->s_luma_data.i4_num_bytes_used_for_ecd; |
| u4_num_bytes += ps_node->ps_child_node_bl->s_luma_data.i4_num_bytes_used_for_ecd; |
| u4_num_bytes += ps_node->ps_child_node_br->s_luma_data.i4_num_bytes_used_for_ecd; |
| |
| if(u1_chroma_processing_enabled) |
| { |
| for(i = 0; i < u1_is_422 + 1; i++) |
| { |
| u4_num_bytes += ps_node->ps_child_node_tl->as_cb_data[i].i4_num_bytes_used_for_ecd; |
| u4_num_bytes += ps_node->ps_child_node_tl->as_cr_data[i].i4_num_bytes_used_for_ecd; |
| u4_num_bytes += ps_node->ps_child_node_tr->as_cb_data[i].i4_num_bytes_used_for_ecd; |
| u4_num_bytes += ps_node->ps_child_node_tr->as_cr_data[i].i4_num_bytes_used_for_ecd; |
| u4_num_bytes += ps_node->ps_child_node_bl->as_cb_data[i].i4_num_bytes_used_for_ecd; |
| u4_num_bytes += ps_node->ps_child_node_bl->as_cr_data[i].i4_num_bytes_used_for_ecd; |
| u4_num_bytes += ps_node->ps_child_node_br->as_cb_data[i].i4_num_bytes_used_for_ecd; |
| u4_num_bytes += ps_node->ps_child_node_br->as_cr_data[i].i4_num_bytes_used_for_ecd; |
| } |
| } |
| } |
| |
| ppu1_ecd[0] = pu1_ecd_buf_ptr_at_t0 + u4_num_bytes; |
| |
| return u4_num_bytes; |
| } |
| |
| static INLINE LWORD64 ihevce_tu_node_cost_collator( |
| tu_tree_node_t *ps_node, UWORD8 u1_chroma_processing_enabled, UWORD8 u1_is_422) |
| { |
| UWORD8 i; |
| |
| LWORD64 i8_cost = 0; |
| |
| i8_cost += ps_node->s_luma_data.i8_cost; |
| |
| if(u1_chroma_processing_enabled) |
| { |
| for(i = 0; i < u1_is_422 + 1; i++) |
| { |
| i8_cost += ps_node->as_cb_data[i].i8_cost; |
| i8_cost += ps_node->as_cr_data[i].i8_cost; |
| } |
| } |
| |
| return i8_cost; |
| } |
| |
| #if !ENABLE_TOP_DOWN_TU_RECURSION |
| /*! |
| ****************************************************************************** |
| * \if Function name : ihevce_tu_processor \endif |
| * |
| * \notes |
| * Determines RDO TU Tree using DFS. If the parent is the winner, then all |
| * pointers to the children nodes are set to NULL |
| * Input : 1. ps_ctxt: Pointer to enc-loop's context. Parts of this structure |
| * shall be modified by this function. They include, au1_cu_csbf, |
| * i8_cu_not_coded_cost, ai2_scratch, s_rdoq_sbh_ctxt, |
| * pi4_quant_round_factor_tu_0_1, pi4_quant_round_factor_tu_1_2, |
| * i4_quant_round_tu |
| * 2. ps_node: Pointer to current node of the TU tree. This struct |
| * shall be modified by this function |
| * 3. pv_recon: Pointer to buffer which stores the recon |
| * This buffer shall be modified by this function |
| * 4. ps_nbr_data_buf: Pointer to struct used by succeeding CU's |
| * during RDOPT. This buffer shall be modifie by this function |
| * 6. pi2_deq_data: Pointer to buffer which stores the output of IQ. |
| * This buffer shall be modified by this function |
| * 7. pu1_ecd: Pointer to buffer which stores the data output by |
| * entropy coding. This buffer shall be modified by this function |
| * 8. pu1_cabac_ctxt: Pointer to buffer which stores the current CABAC |
| * state. This buffer shall be modified by this function |
| * Output : Cost of coding the current branch of the TU tree |
| * |
| ***************************************************************************** |
| */ |
| LWORD64 ihevce_tu_tree_selector( |
| ihevce_enc_loop_ctxt_t *ps_ctxt, |
| tu_tree_node_t *ps_node, |
| buffer_data_for_tu_t *ps_buffer_data, |
| UWORD8 *pu1_cabac_ctxt, |
| WORD32 i4_pred_mode, |
| #if USE_NOISE_TERM_IN_ZERO_CODING_DECISION_ALGORITHMS |
| WORD32 i4_alpha_stim_multiplier, |
| UWORD8 u1_is_cu_noisy, |
| #endif |
| UWORD8 u1_cur_depth, |
| UWORD8 u1_max_depth, |
| UWORD8 u1_part_type, |
| UWORD8 u1_compute_spatial_ssd) |
| { |
| UWORD8 au1_cabac_ctxt_backup[IHEVC_CAB_CTXT_END]; |
| UWORD8 u1_are_children_available; |
| UWORD32 u4_tuSplitFlag_and_cbf_coding_bits; |
| |
| nbr_4x4_t *ps_nbr_data_buf = ps_buffer_data->ps_nbr_data_buf; |
| void *pv_recon_chroma = ps_buffer_data->s_src_pred_rec_buf_chroma.pv_recon; |
| WORD16 *pi2_deq_data = ps_buffer_data->pi2_deq_data; |
| WORD16 *pi2_deq_data_chroma = ps_buffer_data->pi2_deq_data_chroma; |
| UWORD8 **ppu1_ecd = ps_buffer_data->ppu1_ecd; |
| WORD32 i4_nbr_data_buf_stride = ps_buffer_data->i4_nbr_data_buf_stride; |
| WORD32 i4_recon_stride = ps_buffer_data->s_src_pred_rec_buf_luma.i4_recon_stride; |
| WORD32 i4_recon_stride_chroma = ps_buffer_data->s_src_pred_rec_buf_chroma.i4_recon_stride; |
| WORD32 i4_deq_data_stride = ps_buffer_data->i4_deq_data_stride; |
| WORD32 i4_deq_data_stride_chroma = ps_buffer_data->i4_deq_data_stride_chroma; |
| UWORD8 *pu1_ecd_bPtr_backup_t1 = ppu1_ecd[0]; |
| UWORD8 *pu1_ecd_bPtr_backup_t2 = ppu1_ecd[0]; |
| LWORD64 i8_winning_cost = 0; |
| |
| ASSERT(ps_node != NULL); |
| ASSERT( |
| !(!ps_node->u1_is_valid_node && |
| ((NULL == ps_node->ps_child_node_tl) || (NULL == ps_node->ps_child_node_tr) || |
| (NULL == ps_node->ps_child_node_bl) || (NULL == ps_node->ps_child_node_br)))); |
| |
| u1_are_children_available = |
| !((NULL == ps_node->ps_child_node_tl) && (NULL == ps_node->ps_child_node_tr) && |
| (NULL == ps_node->ps_child_node_bl) && (NULL == ps_node->ps_child_node_br)) && |
| (ps_node->s_luma_data.u1_size > MIN_TU_SIZE); |
| |
| if(u1_are_children_available) |
| { |
| if(ps_node->u1_is_valid_node) |
| { |
| memcpy(au1_cabac_ctxt_backup, pu1_cabac_ctxt, sizeof(au1_cabac_ctxt_backup)); |
| } |
| |
| if(i4_pred_mode != PRED_MODE_SKIP) |
| { |
| u4_tuSplitFlag_and_cbf_coding_bits = ihevce_compute_bits_for_TUSplit_and_cbf( |
| ps_node, |
| ps_node->ps_child_node_tl, |
| pu1_cabac_ctxt, |
| MAX_TU_SIZE, |
| MIN_TU_SIZE, |
| 0, |
| 1, |
| i4_pred_mode == PRED_MODE_INTRA, |
| (u1_part_type == PART_NxN) && (i4_pred_mode == PRED_MODE_INTRA), |
| 0, |
| 0); |
| |
| i8_winning_cost += COMPUTE_RATE_COST_CLIP30( |
| u4_tuSplitFlag_and_cbf_coding_bits, |
| ps_ctxt->i8_cl_ssd_lambda_qf, |
| (LAMBDA_Q_SHIFT + CABAC_FRAC_BITS_Q)); |
| } |
| |
| i8_winning_cost += ihevce_tu_tree_selector( |
| ps_ctxt, |
| ps_node->ps_child_node_tl, |
| ps_buffer_data, |
| pu1_cabac_ctxt, |
| i4_pred_mode, |
| #if USE_NOISE_TERM_IN_ZERO_CODING_DECISION_ALGORITHMS |
| i4_alpha_stim_multiplier, |
| u1_is_cu_noisy, |
| #endif |
| u1_cur_depth, |
| u1_max_depth, |
| u1_part_type, |
| u1_compute_spatial_ssd); |
| |
| i8_winning_cost += ihevce_tu_tree_selector( |
| ps_ctxt, |
| ps_node->ps_child_node_tr, |
| ps_buffer_data, |
| pu1_cabac_ctxt, |
| i4_pred_mode, |
| #if USE_NOISE_TERM_IN_ZERO_CODING_DECISION_ALGORITHMS |
| i4_alpha_stim_multiplier, |
| u1_is_cu_noisy, |
| #endif |
| u1_cur_depth, |
| u1_max_depth, |
| u1_part_type, |
| u1_compute_spatial_ssd); |
| |
| i8_winning_cost += ihevce_tu_tree_selector( |
| ps_ctxt, |
| ps_node->ps_child_node_bl, |
| ps_buffer_data, |
| pu1_cabac_ctxt, |
| i4_pred_mode, |
| #if USE_NOISE_TERM_IN_ZERO_CODING_DECISION_ALGORITHMS |
| i4_alpha_stim_multiplier, |
| u1_is_cu_noisy, |
| #endif |
| u1_cur_depth, |
| u1_max_depth, |
| u1_part_type, |
| u1_compute_spatial_ssd); |
| |
| i8_winning_cost += ihevce_tu_tree_selector( |
| ps_ctxt, |
| ps_node->ps_child_node_br, |
| ps_buffer_data, |
| pu1_cabac_ctxt, |
| i4_pred_mode, |
| #if USE_NOISE_TERM_IN_ZERO_CODING_DECISION_ALGORITHMS |
| i4_alpha_stim_multiplier, |
| u1_is_cu_noisy, |
| #endif |
| u1_cur_depth, |
| u1_max_depth, |
| u1_part_type, |
| u1_compute_spatial_ssd); |
| |
| if(ps_node->u1_is_valid_node) |
| { |
| WORD16 ai2_deq_data_backup[MAX_CU_SIZE * MAX_CU_SIZE]; |
| UWORD16 au2_recon_backup[MAX_CU_SIZE * MAX_CU_SIZE]; |
| |
| buffer_data_for_tu_t s_buffer_data = ps_buffer_data[0]; |
| |
| pu1_ecd_bPtr_backup_t2 = ppu1_ecd[0]; |
| s_buffer_data.pi2_deq_data = ai2_deq_data_backup; |
| s_buffer_data.i4_deq_data_stride = MAX_CU_SIZE; |
| s_buffer_data.s_src_pred_rec_buf_luma.pv_recon = au2_recon_backup; |
| s_buffer_data.s_src_pred_rec_buf_luma.i4_recon_stride = MAX_CU_SIZE; |
| |
| ihevce_tu_processor( |
| ps_ctxt, |
| ps_node, |
| &s_buffer_data, |
| au1_cabac_ctxt_backup, |
| i4_pred_mode, |
| #if USE_NOISE_TERM_IN_ZERO_CODING_DECISION_ALGORITHMS |
| i4_alpha_stim_multiplier, |
| u1_is_cu_noisy, |
| #endif |
| 0, |
| u1_compute_spatial_ssd); |
| |
| if(i4_pred_mode != PRED_MODE_SKIP) |
| { |
| u4_tuSplitFlag_and_cbf_coding_bits = ihevce_compute_bits_for_TUSplit_and_cbf( |
| ps_node, |
| ps_node, |
| au1_cabac_ctxt_backup, |
| MAX_TU_SIZE, |
| MIN_TU_SIZE, |
| 0, |
| (u1_cur_depth == u1_max_depth) ? 0 : 1, |
| i4_pred_mode == PRED_MODE_INTRA, |
| (u1_part_type == PART_NxN) && (i4_pred_mode == PRED_MODE_INTRA), |
| 0, |
| 0); |
| |
| ps_node->s_luma_data.i8_cost += COMPUTE_RATE_COST_CLIP30( |
| u4_tuSplitFlag_and_cbf_coding_bits, |
| ps_ctxt->i8_cl_ssd_lambda_qf, |
| (LAMBDA_Q_SHIFT + CABAC_FRAC_BITS_Q)); |
| } |
| |
| if(ps_node->s_luma_data.i8_cost <= i8_winning_cost) |
| { |
| ihevce_debriefer_when_parent_wins( |
| ps_node, |
| ps_ctxt->s_cmn_opt_func.pf_copy_2d, |
| ps_ctxt->s_cmn_opt_func.pf_chroma_interleave_2d_copy, |
| ps_nbr_data_buf, |
| ai2_deq_data_backup, |
| pi2_deq_data, |
| ai2_deq_data_backup + MAX_CU_SIZE * MAX_CU_SIZE, |
| pi2_deq_data_chroma, |
| au2_recon_backup, |
| pv_recon_chroma, |
| au2_recon_backup + MAX_CU_SIZE * MAX_CU_SIZE, |
| pv_recon_chroma, |
| au1_cabac_ctxt_backup, |
| pu1_cabac_ctxt, |
| pu1_ecd_bPtr_backup_t2, |
| pu1_ecd_bPtr_backup_t1, |
| i4_nbr_data_buf_stride, |
| MAX_CU_SIZE, |
| i4_deq_data_stride, |
| MAX_CU_SIZE, |
| i4_deq_data_stride_chroma, |
| MAX_CU_SIZE, |
| i4_recon_stride, |
| MAX_CU_SIZE, |
| i4_recon_stride_chroma, |
| sizeof(au1_cabac_ctxt_backup), |
| ps_ctxt->i4_cu_qp, |
| 0, |
| ps_ctxt->u1_chroma_array_type == 2, |
| ps_ctxt->u1_bit_depth > 8); |
| |
| ppu1_ecd[0] = |
| pu1_ecd_bPtr_backup_t1 + ps_node->s_luma_data.i4_num_bytes_used_for_ecd; |
| i8_winning_cost = ps_node->s_luma_data.i8_cost; |
| } |
| else |
| { |
| ps_node->u1_is_valid_node = 0; |
| } |
| } |
| } |
| else |
| { |
| ASSERT(ps_node->u1_is_valid_node); |
| |
| ihevce_tu_processor( |
| ps_ctxt, |
| ps_node, |
| ps_buffer_data, |
| pu1_cabac_ctxt, |
| i4_pred_mode, |
| #if USE_NOISE_TERM_IN_ZERO_CODING_DECISION_ALGORITHMS |
| i4_alpha_stim_multiplier, |
| u1_is_cu_noisy, |
| #endif |
| 0, |
| u1_compute_spatial_ssd); |
| |
| if(i4_pred_mode != PRED_MODE_SKIP) |
| { |
| u4_tuSplitFlag_and_cbf_coding_bits = ihevce_compute_bits_for_TUSplit_and_cbf( |
| ps_node, |
| ps_node, |
| pu1_cabac_ctxt, |
| MAX_TU_SIZE, |
| MIN_TU_SIZE, |
| 0, |
| (u1_cur_depth == u1_max_depth) ? 0 : 1, |
| i4_pred_mode == PRED_MODE_INTRA, |
| (u1_part_type == PART_NxN) && (i4_pred_mode == PRED_MODE_INTRA), |
| 0, |
| 0); |
| |
| ps_node->s_luma_data.i8_cost += COMPUTE_RATE_COST_CLIP30( |
| u4_tuSplitFlag_and_cbf_coding_bits, |
| ps_ctxt->i8_cl_ssd_lambda_qf, |
| (LAMBDA_Q_SHIFT + CABAC_FRAC_BITS_Q)); |
| } |
| |
| ppu1_ecd[0] = pu1_ecd_bPtr_backup_t1 + ps_node->s_luma_data.i4_num_bytes_used_for_ecd; |
| |
| ihevce_nbr_data_copier( |
| ps_nbr_data_buf, |
| i4_nbr_data_buf_stride, |
| ps_ctxt->i4_cu_qp, |
| ps_node->s_luma_data.u1_cbf, |
| ps_node->s_luma_data.u1_posx, |
| ps_node->s_luma_data.u1_posy, |
| ps_node->s_luma_data.u1_size); |
| |
| i8_winning_cost = ps_node->s_luma_data.i8_cost; |
| } |
| |
| return i8_winning_cost; |
| } |
| #endif |
| |
| /*! |
| ****************************************************************************** |
| * \if Function name : ihevce_topDown_tu_tree_selector \endif |
| * |
| * \notes |
| * Determines RDO TU Tree using DFS. If the parent is the winner, then all |
| * pointers to the children nodes are set to NULL |
| * Input : 1. ps_ctxt: Pointer to enc-loop's context. Parts of this structure |
| * shall be modified by this function. They include, au1_cu_csbf, |
| * i8_cu_not_coded_cost, ai2_scratch, s_rdoq_sbh_ctxt, |
| * pi4_quant_round_factor_tu_0_1, pi4_quant_round_factor_tu_1_2, |
| * i4_quant_round_tu |
| * 2. ps_node: Pointer to current node of the TU tree. This struct |
| * shall be modified by this function |
| * 3. pv_recon: Pointer to buffer which stores the recon |
| * This buffer shall be modified by this function |
| * 4. ps_nbr_data_buf: Pointer to struct used by succeeding CU's |
| * during RDOPT. This buffer shall be modifie by this function |
| * 6. pi2_deq_data: Pointer to buffer which stores the output of IQ. |
| * This buffer shall be modified by this function |
| * 7. pu1_ecd: Pointer to buffer which stores the data output by |
| * entropy coding. This buffer shall be modified by this function |
| * 8. pu1_cabac_ctxt: Pointer to buffer which stores the current CABAC |
| * state. This buffer shall be modified by this function |
| * Output : Cost of coding the current branch of the TU tree |
| * |
| ***************************************************************************** |
| */ |
| LWORD64 ihevce_topDown_tu_tree_selector( |
| ihevce_enc_loop_ctxt_t *ps_ctxt, |
| tu_tree_node_t *ps_node, |
| buffer_data_for_tu_t *ps_buffer_data, |
| UWORD8 *pu1_cabac_ctxt, |
| WORD32 i4_pred_mode, |
| #if USE_NOISE_TERM_IN_ZERO_CODING_DECISION_ALGORITHMS |
| WORD32 i4_alpha_stim_multiplier, |
| UWORD8 u1_is_cu_noisy, |
| #endif |
| UWORD8 u1_cur_depth, |
| UWORD8 u1_max_depth, |
| UWORD8 u1_part_type, |
| UWORD8 u1_chroma_processing_enabled, |
| UWORD8 u1_compute_spatial_ssd) |
| { |
| UWORD8 au1_cabac_ctxt_backup[IHEVC_CAB_CTXT_END]; |
| UWORD8 u1_are_children_available; |
| UWORD32 u4_tuSplitFlag_and_cbf_coding_bits; |
| |
| nbr_4x4_t *ps_nbr_data_buf = ps_buffer_data->ps_nbr_data_buf; |
| |
| void *pv_recon = ps_buffer_data->s_src_pred_rec_buf_luma.pv_recon; |
| void *pv_recon_chroma = ps_buffer_data->s_src_pred_rec_buf_chroma.pv_recon; |
| WORD16 *pi2_deq_data = ps_buffer_data->pi2_deq_data; |
| WORD16 *pi2_deq_data_chroma = ps_buffer_data->pi2_deq_data_chroma; |
| UWORD8 **ppu1_ecd = ps_buffer_data->ppu1_ecd; |
| WORD32 i4_nbr_data_buf_stride = ps_buffer_data->i4_nbr_data_buf_stride; |
| WORD32 i4_recon_stride = ps_buffer_data->s_src_pred_rec_buf_luma.i4_recon_stride; |
| WORD32 i4_recon_stride_chroma = ps_buffer_data->s_src_pred_rec_buf_chroma.i4_recon_stride; |
| WORD32 i4_deq_data_stride = ps_buffer_data->i4_deq_data_stride; |
| WORD32 i4_deq_data_stride_chroma = ps_buffer_data->i4_deq_data_stride_chroma; |
| UWORD8 *pu1_ecd_bPtr_backup_t1 = ppu1_ecd[0]; |
| UWORD8 *pu1_ecd_bPtr_backup_t2 = ppu1_ecd[0]; |
| LWORD64 i8_parent_cost = 0; |
| LWORD64 i8_child_cost = 0; |
| LWORD64 i8_winning_cost = 0; |
| UWORD8 u1_is_422 = (ps_ctxt->u1_chroma_array_type == 2); |
| |
| ASSERT(ps_node != NULL); |
| ASSERT( |
| !(!ps_node->u1_is_valid_node && |
| ((NULL == ps_node->ps_child_node_tl) || (NULL == ps_node->ps_child_node_tr) || |
| (NULL == ps_node->ps_child_node_bl) || (NULL == ps_node->ps_child_node_br)))); |
| |
| u1_are_children_available = |
| !((NULL == ps_node->ps_child_node_tl) && (NULL == ps_node->ps_child_node_tr) && |
| (NULL == ps_node->ps_child_node_bl) && (NULL == ps_node->ps_child_node_br)) && |
| (ps_node->s_luma_data.u1_size > MIN_TU_SIZE); |
| |
| if(u1_are_children_available) |
| { |
| WORD16 ai2_deq_data_backup[MAX_CU_SIZE * MAX_CU_SIZE * 2]; |
| UWORD16 au2_recon_backup[MAX_CU_SIZE * MAX_CU_SIZE * 2]; |
| |
| UWORD8 u1_is_tu_coded = 0; |
| |
| if(ps_node->u1_is_valid_node) |
| { |
| buffer_data_for_tu_t s_buffer_data = ps_buffer_data[0]; |
| |
| memcpy(au1_cabac_ctxt_backup, pu1_cabac_ctxt, sizeof(au1_cabac_ctxt_backup)); |
| |
| s_buffer_data.pi2_deq_data = ai2_deq_data_backup; |
| s_buffer_data.i4_deq_data_stride = MAX_CU_SIZE; |
| s_buffer_data.pi2_deq_data_chroma = ai2_deq_data_backup + MAX_CU_SIZE * MAX_CU_SIZE; |
| s_buffer_data.i4_deq_data_stride_chroma = MAX_CU_SIZE; |
| s_buffer_data.s_src_pred_rec_buf_luma.pv_recon = au2_recon_backup; |
| s_buffer_data.s_src_pred_rec_buf_luma.i4_recon_stride = MAX_CU_SIZE; |
| s_buffer_data.s_src_pred_rec_buf_chroma.pv_recon = |
| au2_recon_backup + MAX_CU_SIZE * MAX_CU_SIZE; |
| s_buffer_data.s_src_pred_rec_buf_chroma.i4_recon_stride = MAX_CU_SIZE; |
| |
| ihevce_tu_processor( |
| ps_ctxt, |
| ps_node, |
| &s_buffer_data, |
| au1_cabac_ctxt_backup, |
| i4_pred_mode, |
| #if USE_NOISE_TERM_IN_ZERO_CODING_DECISION_ALGORITHMS |
| i4_alpha_stim_multiplier, |
| u1_is_cu_noisy, |
| #endif |
| u1_chroma_processing_enabled, |
| u1_compute_spatial_ssd); |
| |
| if(i4_pred_mode != PRED_MODE_SKIP) |
| { |
| u4_tuSplitFlag_and_cbf_coding_bits = ihevce_compute_bits_for_TUSplit_and_cbf( |
| ps_node, |
| ps_node, |
| au1_cabac_ctxt_backup, |
| MAX_TU_SIZE, |
| MIN_TU_SIZE, |
| 0, |
| (u1_cur_depth == u1_max_depth) ? 0 : 1, |
| i4_pred_mode == PRED_MODE_INTRA, |
| (u1_part_type == PART_NxN) && (i4_pred_mode == PRED_MODE_INTRA), |
| u1_chroma_processing_enabled, |
| u1_is_422); |
| |
| ps_node->s_luma_data.i8_cost += COMPUTE_RATE_COST_CLIP30( |
| u4_tuSplitFlag_and_cbf_coding_bits, |
| ps_ctxt->i8_cl_ssd_lambda_qf, |
| (LAMBDA_Q_SHIFT + CABAC_FRAC_BITS_Q)); |
| } |
| |
| i8_parent_cost += |
| ihevce_tu_node_cost_collator(ps_node, u1_chroma_processing_enabled, u1_is_422); |
| |
| ihevce_ecd_buffer_pointer_updater( |
| ps_node, |
| ppu1_ecd, |
| pu1_ecd_bPtr_backup_t1, |
| 1, |
| u1_chroma_processing_enabled, |
| u1_is_422); |
| } |
| else |
| { |
| ps_node->s_luma_data.i8_cost = i8_parent_cost = LLONG_MAX; |
| ps_node->s_luma_data.i4_num_bytes_used_for_ecd = 0; |
| } |
| |
| u1_is_tu_coded |= ps_node->s_luma_data.u1_cbf; |
| |
| if(u1_chroma_processing_enabled) |
| { |
| UWORD8 i; |
| |
| for(i = 0; i < u1_is_422 + 1; i++) |
| { |
| u1_is_tu_coded |= ps_node->as_cb_data[i].u1_cbf; |
| u1_is_tu_coded |= ps_node->as_cr_data[i].u1_cbf; |
| } |
| } |
| |
| if(!ps_node->u1_is_valid_node || u1_is_tu_coded) |
| { |
| pu1_ecd_bPtr_backup_t2 = ppu1_ecd[0]; |
| |
| if(i4_pred_mode != PRED_MODE_SKIP) |
| { |
| u4_tuSplitFlag_and_cbf_coding_bits = ihevce_compute_bits_for_TUSplit_and_cbf( |
| ps_node, |
| ps_node->ps_child_node_tl, |
| pu1_cabac_ctxt, |
| MAX_TU_SIZE, |
| MIN_TU_SIZE, |
| 0, |
| 1, |
| i4_pred_mode == PRED_MODE_INTRA, |
| (u1_part_type == PART_NxN) && (i4_pred_mode == PRED_MODE_INTRA), |
| u1_chroma_processing_enabled, |
| u1_is_422); |
| |
| i8_child_cost += COMPUTE_RATE_COST_CLIP30( |
| u4_tuSplitFlag_and_cbf_coding_bits, |
| ps_ctxt->i8_cl_ssd_lambda_qf, |
| (LAMBDA_Q_SHIFT + CABAC_FRAC_BITS_Q)); |
| } |
| |
| if(i8_child_cost < i8_parent_cost) |
| { |
| i8_child_cost += ihevce_topDown_tu_tree_selector( |
| ps_ctxt, |
| ps_node->ps_child_node_tl, |
| ps_buffer_data, |
| pu1_cabac_ctxt, |
| i4_pred_mode, |
| #if USE_NOISE_TERM_IN_ZERO_CODING_DECISION_ALGORITHMS |
| i4_alpha_stim_multiplier, |
| u1_is_cu_noisy, |
| #endif |
| u1_cur_depth, |
| u1_max_depth, |
| u1_part_type, |
| u1_chroma_processing_enabled, |
| u1_compute_spatial_ssd); |
| |
| ps_node->ps_child_node_tl->s_luma_data.i8_cost += |
| i8_child_cost - ps_node->ps_child_node_tl->s_luma_data.i8_cost; |
| } |
| |
| if(i8_child_cost < i8_parent_cost) |
| { |
| i8_child_cost += ihevce_topDown_tu_tree_selector( |
| ps_ctxt, |
| ps_node->ps_child_node_tr, |
| ps_buffer_data, |
| pu1_cabac_ctxt, |
| i4_pred_mode, |
| #if USE_NOISE_TERM_IN_ZERO_CODING_DECISION_ALGORITHMS |
| i4_alpha_stim_multiplier, |
| u1_is_cu_noisy, |
| #endif |
| u1_cur_depth, |
| u1_max_depth, |
| u1_part_type, |
| u1_chroma_processing_enabled, |
| u1_compute_spatial_ssd); |
| } |
| |
| if(i8_child_cost < i8_parent_cost) |
| { |
| i8_child_cost += ihevce_topDown_tu_tree_selector( |
| ps_ctxt, |
| ps_node->ps_child_node_bl, |
| ps_buffer_data, |
| pu1_cabac_ctxt, |
| i4_pred_mode, |
| #if USE_NOISE_TERM_IN_ZERO_CODING_DECISION_ALGORITHMS |
| i4_alpha_stim_multiplier, |
| u1_is_cu_noisy, |
| #endif |
| u1_cur_depth, |
| u1_max_depth, |
| u1_part_type, |
| u1_chroma_processing_enabled, |
| u1_compute_spatial_ssd); |
| } |
| |
| if(i8_child_cost < i8_parent_cost) |
| { |
| i8_child_cost += ihevce_topDown_tu_tree_selector( |
| ps_ctxt, |
| ps_node->ps_child_node_br, |
| ps_buffer_data, |
| pu1_cabac_ctxt, |
| i4_pred_mode, |
| #if USE_NOISE_TERM_IN_ZERO_CODING_DECISION_ALGORITHMS |
| i4_alpha_stim_multiplier, |
| u1_is_cu_noisy, |
| #endif |
| u1_cur_depth, |
| u1_max_depth, |
| u1_part_type, |
| u1_chroma_processing_enabled, |
| u1_compute_spatial_ssd); |
| } |
| |
| if(i8_parent_cost > i8_child_cost) |
| { |
| UWORD32 u4_num_bytes = ihevce_ecd_buffer_pointer_updater( |
| ps_node, |
| ppu1_ecd, |
| pu1_ecd_bPtr_backup_t1, |
| 0, |
| u1_chroma_processing_enabled, |
| u1_is_422); |
| |
| if(pu1_ecd_bPtr_backup_t2 != pu1_ecd_bPtr_backup_t1) |
| { |
| memmove(pu1_ecd_bPtr_backup_t1, pu1_ecd_bPtr_backup_t2, u4_num_bytes); |
| } |
| |
| ps_node->s_luma_data.i4_num_bytes_used_for_ecd = u4_num_bytes; |
| ps_node->as_cb_data[0].i4_num_bytes_used_for_ecd = 0; |
| ps_node->as_cb_data[1].i4_num_bytes_used_for_ecd = 0; |
| ps_node->as_cr_data[0].i4_num_bytes_used_for_ecd = 0; |
| ps_node->as_cr_data[1].i4_num_bytes_used_for_ecd = 0; |
| |
| ps_node->u1_is_valid_node = 0; |
| |
| i8_winning_cost = i8_child_cost; |
| } |
| else |
| { |
| ihevce_debriefer_when_parent_wins( |
| ps_node, |
| ps_ctxt->s_cmn_opt_func.pf_copy_2d, |
| ps_ctxt->s_cmn_opt_func.pf_chroma_interleave_2d_copy, |
| ps_nbr_data_buf, |
| ai2_deq_data_backup, |
| pi2_deq_data, |
| ai2_deq_data_backup + MAX_CU_SIZE * MAX_CU_SIZE, |
| pi2_deq_data_chroma, |
| au2_recon_backup, |
| pv_recon, |
| au2_recon_backup + MAX_CU_SIZE * MAX_CU_SIZE, |
| pv_recon_chroma, |
| au1_cabac_ctxt_backup, |
| pu1_cabac_ctxt, |
| NULL, |
| NULL, |
| i4_nbr_data_buf_stride, |
| MAX_CU_SIZE, |
| i4_deq_data_stride, |
| MAX_CU_SIZE, |
| i4_deq_data_stride_chroma, |
| MAX_CU_SIZE, |
| i4_recon_stride, |
| MAX_CU_SIZE, |
| i4_recon_stride_chroma, |
| sizeof(au1_cabac_ctxt_backup), |
| ps_ctxt->i4_cu_qp, |
| u1_chroma_processing_enabled, |
| u1_is_422, |
| ps_ctxt->u1_bit_depth > 8); |
| |
| ihevce_ecd_buffer_pointer_updater( |
| ps_node, |
| ppu1_ecd, |
| pu1_ecd_bPtr_backup_t1, |
| 1, |
| u1_chroma_processing_enabled, |
| u1_is_422); |
| |
| i8_winning_cost = i8_parent_cost; |
| } |
| } |
| else |
| { |
| ihevce_debriefer_when_parent_wins( |
| ps_node, |
| ps_ctxt->s_cmn_opt_func.pf_copy_2d, |
| ps_ctxt->s_cmn_opt_func.pf_chroma_interleave_2d_copy, |
| ps_nbr_data_buf, |
| ai2_deq_data_backup, |
| pi2_deq_data, |
| ai2_deq_data_backup + MAX_CU_SIZE * MAX_CU_SIZE, |
| pi2_deq_data_chroma, |
| au2_recon_backup, |
| pv_recon, |
| au2_recon_backup + MAX_CU_SIZE * MAX_CU_SIZE, |
| pv_recon_chroma, |
| au1_cabac_ctxt_backup, |
| pu1_cabac_ctxt, |
| NULL, |
| NULL, |
| i4_nbr_data_buf_stride, |
| MAX_CU_SIZE, |
| i4_deq_data_stride, |
| MAX_CU_SIZE, |
| i4_deq_data_stride_chroma, |
| MAX_CU_SIZE, |
| i4_recon_stride, |
| MAX_CU_SIZE, |
| i4_recon_stride_chroma, |
| sizeof(au1_cabac_ctxt_backup), |
| ps_ctxt->i4_cu_qp, |
| u1_chroma_processing_enabled, |
| u1_is_422, |
| ps_ctxt->u1_bit_depth > 8); |
| |
| ihevce_ecd_buffer_pointer_updater( |
| ps_node, |
| ppu1_ecd, |
| pu1_ecd_bPtr_backup_t1, |
| 1, |
| u1_chroma_processing_enabled, |
| u1_is_422); |
| |
| i8_winning_cost = i8_parent_cost; |
| } |
| } |
| else |
| { |
| ASSERT(ps_node->u1_is_valid_node); |
| |
| ihevce_tu_processor( |
| ps_ctxt, |
| ps_node, |
| ps_buffer_data, |
| pu1_cabac_ctxt, |
| i4_pred_mode, |
| #if USE_NOISE_TERM_IN_ZERO_CODING_DECISION_ALGORITHMS |
| i4_alpha_stim_multiplier, |
| u1_is_cu_noisy, |
| #endif |
| u1_chroma_processing_enabled, |
| u1_compute_spatial_ssd); |
| |
| if(i4_pred_mode != PRED_MODE_SKIP) |
| { |
| u4_tuSplitFlag_and_cbf_coding_bits = ihevce_compute_bits_for_TUSplit_and_cbf( |
| ps_node, |
| ps_node, |
| pu1_cabac_ctxt, |
| MAX_TU_SIZE, |
| MIN_TU_SIZE, |
| 0, |
| (u1_cur_depth == u1_max_depth) ? 0 : 1, |
| i4_pred_mode == PRED_MODE_INTRA, |
| (u1_part_type == PART_NxN) && (i4_pred_mode == PRED_MODE_INTRA), |
| u1_chroma_processing_enabled, |
| u1_is_422); |
| |
| ps_node->s_luma_data.i8_cost += COMPUTE_RATE_COST_CLIP30( |
| u4_tuSplitFlag_and_cbf_coding_bits, |
| ps_ctxt->i8_cl_ssd_lambda_qf, |
| (LAMBDA_Q_SHIFT + CABAC_FRAC_BITS_Q)); |
| } |
| |
| i8_winning_cost += |
| ihevce_tu_node_cost_collator(ps_node, u1_chroma_processing_enabled, u1_is_422); |
| |
| ihevce_ecd_buffer_pointer_updater( |
| ps_node, ppu1_ecd, pu1_ecd_bPtr_backup_t1, 1, u1_chroma_processing_enabled, u1_is_422); |
| |
| ihevce_nbr_data_copier( |
| ps_nbr_data_buf, |
| i4_nbr_data_buf_stride, |
| ps_ctxt->i4_cu_qp, |
| ps_node->s_luma_data.u1_cbf, |
| ps_node->s_luma_data.u1_posx, |
| ps_node->s_luma_data.u1_posy, |
| ps_node->s_luma_data.u1_size); |
| } |
| |
| return i8_winning_cost; |
| } |
| |
| /*! |
| ****************************************************************************** |
| * \if Function name : ihevce_tu_selector_debriefer \endif |
| * |
| * \notes |
| * Conversion of TU Tree struct into TU info array. Collection of myriad CU |
| * level data |
| * Input : 1. ps_node: Pointer to current node of the TU tree. This struct |
| * shall be modified by this function |
| * 2. ps_final_prms: Pointer to struct that stores RDOPT output data. |
| * This buffer shall be modified by this function |
| * Output : 1. pi8_total_cost: Total CU-level cost |
| * 2. pi8_total_non_coded_cost: Total CU level cost when no residue |
| * is coded |
| * 3. pi4_num_bytes_used_for_ecd: Number of bytes used for storing |
| * entropy coding data |
| * 4. pi4_num_bits_used_for_encoding: Number of bits used for encoding |
| * 5. pu2_tu_ctr: Number of TU's in the CU |
| * |
| ***************************************************************************** |
| */ |
| void ihevce_tu_selector_debriefer( |
| tu_tree_node_t *ps_node, |
| enc_loop_cu_final_prms_t *ps_final_prms, |
| LWORD64 *pi8_total_cost, |
| LWORD64 *pi8_total_non_coded_cost, |
| WORD32 *pi4_num_bytes_used_for_ecd, |
| WORD32 *pi4_num_bits_used_for_encoding, |
| UWORD16 *pu2_tu_ctr, |
| WORD32 i4_cu_qp, |
| UWORD8 u1_cu_posx, |
| UWORD8 u1_cu_posy, |
| UWORD8 u1_chroma_processing_enabled, |
| UWORD8 u1_is_422, |
| TU_POS_T e_tu_pos) |
| { |
| UWORD8 u1_is_chroma_tu_valid = 1; |
| WORD32 i4_log2_size; |
| |
| ASSERT(ps_node != NULL); |
| |
| if(ps_node->u1_is_valid_node) |
| { |
| ASSERT( |
| (NULL == ps_node->ps_child_node_tl) && (NULL == ps_node->ps_child_node_tr) && |
| (NULL == ps_node->ps_child_node_bl) && (NULL == ps_node->ps_child_node_br)); |
| } |
| else |
| { |
| ASSERT( |
| !((NULL == ps_node->ps_child_node_tl) || (NULL == ps_node->ps_child_node_tr) || |
| (NULL == ps_node->ps_child_node_bl) || (NULL == ps_node->ps_child_node_br))); |
| } |
| |
| if(ps_node->u1_is_valid_node) |
| { |
| if((4 == ps_node->s_luma_data.u1_size) && (POS_TL != e_tu_pos)) |
| { |
| u1_is_chroma_tu_valid = INTRA_PRED_CHROMA_IDX_NONE; |
| } |
| |
| GETRANGE(i4_log2_size, ps_node->s_luma_data.u1_size); |
| |
| ps_final_prms->s_recon_datastore.au1_bufId_with_winning_LumaRecon[pu2_tu_ctr[0]] = |
| ps_node->s_luma_data.u1_reconBufId; |
| ps_final_prms->u4_cu_sad += ps_node->s_luma_data.u4_sad; |
| ps_final_prms->u1_is_cu_coded |= ps_node->s_luma_data.u1_cbf; |
| ps_final_prms->u4_cu_luma_res_bits += ps_node->s_luma_data.i4_bits; |
| |
| ps_final_prms->as_tu_enc_loop[pu2_tu_ctr[0]].i4_luma_coeff_offset = |
| pi4_num_bytes_used_for_ecd[0]; |
| ps_final_prms->as_tu_enc_loop[pu2_tu_ctr[0]].s_tu.b1_y_cbf = ps_node->s_luma_data.u1_cbf; |
| ps_final_prms->as_tu_enc_loop[pu2_tu_ctr[0]].s_tu.b1_cb_cbf = 0; |
| ps_final_prms->as_tu_enc_loop[pu2_tu_ctr[0]].s_tu.b1_cr_cbf = 0; |
| ps_final_prms->as_tu_enc_loop[pu2_tu_ctr[0]].s_tu.b1_cb_cbf_subtu1 = 0; |
| ps_final_prms->as_tu_enc_loop[pu2_tu_ctr[0]].s_tu.b1_cr_cbf_subtu1 = 0; |
| ps_final_prms->as_tu_enc_loop[pu2_tu_ctr[0]].s_tu.b3_chroma_intra_mode_idx = |
| u1_is_chroma_tu_valid; |
| ps_final_prms->as_tu_enc_loop[pu2_tu_ctr[0]].s_tu.b7_qp = i4_cu_qp; |
| ps_final_prms->as_tu_enc_loop[pu2_tu_ctr[0]].s_tu.b1_first_tu_in_cu = |
| (!ps_node->s_luma_data.u1_posx && !ps_node->s_luma_data.u1_posx); |
| ps_final_prms->as_tu_enc_loop[pu2_tu_ctr[0]].s_tu.b1_transquant_bypass = 0; |
| ps_final_prms->as_tu_enc_loop[pu2_tu_ctr[0]].s_tu.b3_size = i4_log2_size - 3; |
| ps_final_prms->as_tu_enc_loop[pu2_tu_ctr[0]].s_tu.b4_pos_x = |
| (u1_cu_posx + ps_node->s_luma_data.u1_posx) / 4; |
| ps_final_prms->as_tu_enc_loop[pu2_tu_ctr[0]].s_tu.b4_pos_y = |
| (u1_cu_posy + ps_node->s_luma_data.u1_posy) / 4; |
| |
| ps_final_prms->as_tu_enc_loop_temp_prms[pu2_tu_ctr[0]].i2_luma_bytes_consumed = |
| ps_node->s_luma_data.i4_num_bytes_used_for_ecd; |
| ps_final_prms->as_tu_enc_loop_temp_prms[pu2_tu_ctr[0]].u4_luma_zero_col = |
| ps_node->s_luma_data.i4_zero_col; |
| ps_final_prms->as_tu_enc_loop_temp_prms[pu2_tu_ctr[0]].u4_luma_zero_row = |
| ps_node->s_luma_data.i4_zero_row; |
| |
| pi8_total_cost[0] += ps_node->s_luma_data.i8_cost; |
| pi8_total_non_coded_cost[0] += ps_node->s_luma_data.i8_not_coded_cost; |
| pi4_num_bytes_used_for_ecd[0] += ps_node->s_luma_data.i4_num_bytes_used_for_ecd; |
| pi4_num_bits_used_for_encoding[0] += ps_node->s_luma_data.i4_bits; |
| |
| if(u1_chroma_processing_enabled) |
| { |
| UWORD8 i; |
| |
| for(i = 0; i < u1_is_422 + 1; i++) |
| { |
| ps_final_prms->s_recon_datastore |
| .au1_bufId_with_winning_ChromaRecon[U_PLANE][pu2_tu_ctr[0]][i] = |
| ps_node->as_cb_data[i].u1_reconBufId; |
| ps_final_prms->u1_is_cu_coded |= ps_node->as_cb_data[i].u1_cbf; |
| ps_final_prms->u4_cu_chroma_res_bits += ps_node->as_cb_data[i].i4_bits; |
| |
| ps_final_prms->as_tu_enc_loop[pu2_tu_ctr[0]].ai4_cb_coeff_offset[i] = |
| pi4_num_bytes_used_for_ecd[0]; |
| |
| if(!i) |
| { |
| ps_final_prms->as_tu_enc_loop[pu2_tu_ctr[0]].s_tu.b1_cb_cbf = |
| ps_node->as_cb_data[i].u1_cbf; |
| } |
| else |
| { |
| ps_final_prms->as_tu_enc_loop[pu2_tu_ctr[0]].s_tu.b1_cb_cbf_subtu1 = |
| ps_node->as_cb_data[i].u1_cbf; |
| } |
| |
| ps_final_prms->as_tu_enc_loop_temp_prms[pu2_tu_ctr[0]].ai2_cb_bytes_consumed[i] = |
| ps_node->as_cb_data[i].i4_num_bytes_used_for_ecd; |
| ps_final_prms->as_tu_enc_loop_temp_prms[pu2_tu_ctr[0]].au4_cb_zero_col[i] = |
| ps_node->as_cb_data[i].i4_zero_col; |
| ps_final_prms->as_tu_enc_loop_temp_prms[pu2_tu_ctr[0]].au4_cb_zero_row[i] = |
| ps_node->as_cb_data[i].i4_zero_row; |
| |
| pi8_total_cost[0] += ps_node->as_cb_data[i].i8_cost; |
| pi8_total_non_coded_cost[0] += ps_node->as_cb_data[i].i8_not_coded_cost; |
| pi4_num_bytes_used_for_ecd[0] += ps_node->as_cb_data[i].i4_num_bytes_used_for_ecd; |
| pi4_num_bits_used_for_encoding[0] += ps_node->as_cb_data[i].i4_bits; |
| } |
| |
| for(i = 0; i < u1_is_422 + 1; i++) |
| { |
| ps_final_prms->s_recon_datastore |
| .au1_bufId_with_winning_ChromaRecon[V_PLANE][pu2_tu_ctr[0]][i] = |
| ps_node->as_cr_data[i].u1_reconBufId; |
| ps_final_prms->u1_is_cu_coded |= ps_node->as_cr_data[i].u1_cbf; |
| ps_final_prms->u4_cu_chroma_res_bits += ps_node->as_cr_data[i].i4_bits; |
| |
| ps_final_prms->as_tu_enc_loop[pu2_tu_ctr[0]].ai4_cr_coeff_offset[i] = |
| pi4_num_bytes_used_for_ecd[0]; |
| |
| if(!i) |
| { |
| ps_final_prms->as_tu_enc_loop[pu2_tu_ctr[0]].s_tu.b1_cr_cbf = |
| ps_node->as_cr_data[i].u1_cbf; |
| } |
| else |
| { |
| ps_final_prms->as_tu_enc_loop[pu2_tu_ctr[0]].s_tu.b1_cr_cbf_subtu1 = |
| ps_node->as_cr_data[i].u1_cbf; |
| } |
| |
| ps_final_prms->as_tu_enc_loop_temp_prms[pu2_tu_ctr[0]].ai2_cr_bytes_consumed[i] = |
| ps_node->as_cr_data[i].i4_num_bytes_used_for_ecd; |
| ps_final_prms->as_tu_enc_loop_temp_prms[pu2_tu_ctr[0]].au4_cr_zero_col[i] = |
| ps_node->as_cr_data[i].i4_zero_col; |
| ps_final_prms->as_tu_enc_loop_temp_prms[pu2_tu_ctr[0]].au4_cr_zero_row[i] = |
| ps_node->as_cr_data[i].i4_zero_row; |
| |
| pi8_total_cost[0] += ps_node->as_cr_data[i].i8_cost; |
| pi8_total_non_coded_cost[0] += ps_node->as_cr_data[i].i8_not_coded_cost; |
| pi4_num_bytes_used_for_ecd[0] += ps_node->as_cr_data[i].i4_num_bytes_used_for_ecd; |
| pi4_num_bits_used_for_encoding[0] += ps_node->as_cr_data[i].i4_bits; |
| } |
| } |
| |
| pu2_tu_ctr[0]++; |
| } |
| else |
| { |
| ihevce_tu_selector_debriefer( |
| ps_node->ps_child_node_tl, |
| ps_final_prms, |
| pi8_total_cost, |
| pi8_total_non_coded_cost, |
| pi4_num_bytes_used_for_ecd, |
| pi4_num_bits_used_for_encoding, |
| pu2_tu_ctr, |
| i4_cu_qp, |
| u1_cu_posx, |
| u1_cu_posy, |
| u1_chroma_processing_enabled, |
| u1_is_422, |
| POS_TL); |
| |
| ihevce_tu_selector_debriefer( |
| ps_node->ps_child_node_tr, |
| ps_final_prms, |
| pi8_total_cost, |
| pi8_total_non_coded_cost, |
| pi4_num_bytes_used_for_ecd, |
| pi4_num_bits_used_for_encoding, |
| pu2_tu_ctr, |
| i4_cu_qp, |
| u1_cu_posx, |
| u1_cu_posy, |
| u1_chroma_processing_enabled, |
| u1_is_422, |
| POS_TR); |
| |
| ihevce_tu_selector_debriefer( |
| ps_node->ps_child_node_bl, |
| ps_final_prms, |
| pi8_total_cost, |
| pi8_total_non_coded_cost, |
| pi4_num_bytes_used_for_ecd, |
| pi4_num_bits_used_for_encoding, |
| pu2_tu_ctr, |
| i4_cu_qp, |
| u1_cu_posx, |
| u1_cu_posy, |
| u1_chroma_processing_enabled, |
| u1_is_422, |
| POS_BL); |
| |
| ihevce_tu_selector_debriefer( |
| ps_node->ps_child_node_br, |
| ps_final_prms, |
| pi8_total_cost, |
| pi8_total_non_coded_cost, |
| pi4_num_bytes_used_for_ecd, |
| pi4_num_bits_used_for_encoding, |
| pu2_tu_ctr, |
| i4_cu_qp, |
| u1_cu_posx, |
| u1_cu_posy, |
| u1_chroma_processing_enabled, |
| u1_is_422, |
| POS_BR); |
| } |
| } |
| |
| static UWORD8 ihevce_get_curTUSplit_from_TUSplitArray( |
| WORD32 ai4_tuSplitArray[4], UWORD8 u1_cu_size, UWORD8 u1_tu_size, UWORD8 u1_posx, UWORD8 u1_posy) |
| { |
| UWORD8 u1_is_split = 0; |
| |
| UWORD8 u1_tuSplitArrayIndex = 0; |
| UWORD8 u1_bit_index = 0; |
| |
| switch(u1_cu_size) |
| { |
| case 8: |
| { |
| switch(u1_tu_size) |
| { |
| case 8: |
| { |
| u1_is_split = !!(ai4_tuSplitArray[u1_tuSplitArrayIndex] & BIT_EN(u1_bit_index)); |
| |
| break; |
| } |
| case 4: |
| { |
| u1_is_split = 0; |
| |
| break; |
| } |
| } |
| |
| break; |
| } |
| case 16: |
| { |
| switch(u1_tu_size) |
| { |
| case 16: |
| { |
| u1_is_split = !!(ai4_tuSplitArray[u1_tuSplitArrayIndex] & BIT_EN(u1_bit_index)); |
| |
| break; |
| } |
| case 8: |
| { |
| u1_bit_index += ((u1_posx / 8) % 2) + 2 * ((u1_posy / 8) % 2) + 1; |
| u1_is_split = !!(ai4_tuSplitArray[u1_tuSplitArrayIndex] & BIT_EN(u1_bit_index)); |
| |
| break; |
| } |
| case 4: |
| { |
| u1_is_split = 0; |
| |
| break; |
| } |
| } |
| |
| break; |
| } |
| case 32: |
| { |
| switch(u1_tu_size) |
| { |
| case 32: |
| { |
| u1_is_split = !!(ai4_tuSplitArray[u1_tuSplitArrayIndex] & BIT_EN(u1_bit_index)); |
| |
| break; |
| } |
| case 16: |
| { |
| u1_bit_index += 5 * ((u1_posx / 16) % 2) + 10 * ((u1_posy / 16) % 2) + 1; |
| u1_is_split = !!(ai4_tuSplitArray[u1_tuSplitArrayIndex] & BIT_EN(u1_bit_index)); |
| |
| break; |
| } |
| case 8: |
| { |
| u1_bit_index = 5 * ((u1_posx / 16) % 2) + 10 * ((u1_posy / 16) % 2) + 1; |
| u1_bit_index += ((u1_posx / 8) % 2) + 2 * ((u1_posy / 8) % 2) + 1; |
| u1_is_split = !!(ai4_tuSplitArray[u1_tuSplitArrayIndex] & BIT_EN(u1_bit_index)); |
| |
| break; |
| } |
| case 4: |
| { |
| u1_is_split = 0; |
| |
| break; |
| } |
| } |
| |
| break; |
| } |
| case 64: |
| { |
| switch(u1_tu_size) |
| { |
| case 64: |
| { |
| u1_is_split = 1; |
| |
| break; |
| } |
| case 32: |
| { |
| u1_tuSplitArrayIndex = ((u1_posx / 32) % 2) + 2 * ((u1_posy / 32) % 2); |
| u1_is_split = !!(ai4_tuSplitArray[u1_tuSplitArrayIndex] & BIT_EN(u1_bit_index)); |
| |
| break; |
| } |
| case 16: |
| { |
| u1_tuSplitArrayIndex = ((u1_posx / 32) % 2) + 2 * ((u1_posy / 32) % 2); |
| u1_bit_index += 5 * ((u1_posx / 16) % 2) + 10 * ((u1_posy / 16) % 2) + 1; |
| u1_is_split = !!(ai4_tuSplitArray[u1_tuSplitArrayIndex] & BIT_EN(u1_bit_index)); |
| |
| break; |
| } |
| case 8: |
| { |
| u1_tuSplitArrayIndex = ((u1_posx / 32) % 2) + 2 * ((u1_posy / 32) % 2); |
| u1_bit_index += 5 * ((u1_posx / 16) % 2) + 10 * ((u1_posy / 16) % 2) + 1; |
| u1_bit_index += ((u1_posx / 8) % 2) + 2 * ((u1_posy / 8) % 2) + 1; |
| u1_is_split = !!(ai4_tuSplitArray[u1_tuSplitArrayIndex] & BIT_EN(u1_bit_index)); |
| |
| break; |
| } |
| case 4: |
| { |
| u1_is_split = 0; |
| |
| break; |
| } |
| } |
| |
| break; |
| } |
| } |
| |
| return u1_is_split; |
| } |
| |
| /*! |
| ****************************************************************************** |
| * \if Function name : ihevce_tuSplitArray_to_tuTree_mapper \endif |
| * |
| * \notes |
| * This function assumes that ihevce_tu_tree_init' has been called already. |
| * The pointers to the children nodes of the leaf-most nodes in the tree |
| * are assigned NULL |
| * Input : 1. ps_root: Pointer to root of the tree containing TU info. |
| * This struct shall be modified by this function |
| * 2. ai4_tuSplitArray: Array containing information about TU splits |
| * Output : 1. TU tree is modified such that it reflects the information |
| * coded in ai4_tuSplitArray |
| * |
| ***************************************************************************** |
| */ |
| void ihevce_tuSplitArray_to_tuTree_mapper( |
| tu_tree_node_t *ps_root, |
| WORD32 ai4_tuSplitArray[4], |
| UWORD8 u1_cu_size, |
| UWORD8 u1_tu_size, |
| UWORD8 u1_min_tu_size, |
| UWORD8 u1_max_tu_size, |
| UWORD8 u1_is_skip) |
| { |
| UWORD8 u1_is_split; |
| |
| ASSERT(u1_min_tu_size >= MIN_TU_SIZE); |
| ASSERT(u1_max_tu_size <= MAX_TU_SIZE); |
| ASSERT(u1_min_tu_size <= u1_max_tu_size); |
| |
| ASSERT(!u1_is_skip); |
| |
| ASSERT(ps_root != NULL); |
| ASSERT(ps_root->s_luma_data.u1_size == u1_tu_size); |
| |
| if(u1_tu_size <= u1_max_tu_size) |
| { |
| ASSERT(ps_root->u1_is_valid_node); |
| } |
| else |
| { |
| ASSERT(!ps_root->u1_is_valid_node); |
| } |
| |
| if(u1_tu_size > u1_min_tu_size) |
| { |
| ASSERT(ps_root->ps_child_node_tl != NULL); |
| ASSERT(ps_root->ps_child_node_tr != NULL); |
| ASSERT(ps_root->ps_child_node_bl != NULL); |
| ASSERT(ps_root->ps_child_node_br != NULL); |
| ASSERT(ps_root->ps_child_node_tl->s_luma_data.u1_size == (u1_tu_size / 2)); |
| ASSERT(ps_root->ps_child_node_tr->s_luma_data.u1_size == (u1_tu_size / 2)); |
| ASSERT(ps_root->ps_child_node_bl->s_luma_data.u1_size == (u1_tu_size / 2)); |
| ASSERT(ps_root->ps_child_node_br->s_luma_data.u1_size == (u1_tu_size / 2)); |
| ASSERT(ps_root->ps_child_node_tl->u1_is_valid_node); |
| ASSERT(ps_root->ps_child_node_tr->u1_is_valid_node); |
| ASSERT(ps_root->ps_child_node_bl->u1_is_valid_node); |
| ASSERT(ps_root->ps_child_node_br->u1_is_valid_node); |
| } |
| else |
| { |
| ASSERT(ps_root->ps_child_node_tl == NULL); |
| ASSERT(ps_root->ps_child_node_tr == NULL); |
| ASSERT(ps_root->ps_child_node_bl == NULL); |
| ASSERT(ps_root->ps_child_node_br == NULL); |
| } |
| |
| u1_is_split = ihevce_get_curTUSplit_from_TUSplitArray( |
| ai4_tuSplitArray, |
| u1_cu_size, |
| u1_tu_size, |
| ps_root->s_luma_data.u1_posx, |
| ps_root->s_luma_data.u1_posy); |
| |
| if(u1_tu_size == u1_min_tu_size) |
| { |
| ASSERT(!u1_is_split); |
| } |
| |
| if(u1_is_split) |
| { |
| ps_root->u1_is_valid_node = 0; |
| |
| ihevce_tuSplitArray_to_tuTree_mapper( |
| ps_root->ps_child_node_tl, |
| ai4_tuSplitArray, |
| u1_cu_size, |
| ps_root->ps_child_node_tl->s_luma_data.u1_size, |
| u1_min_tu_size, |
| u1_max_tu_size, |
| u1_is_skip); |
| |
| ihevce_tuSplitArray_to_tuTree_mapper( |
| ps_root->ps_child_node_tr, |
| ai4_tuSplitArray, |
| u1_cu_size, |
| ps_root->ps_child_node_tr->s_luma_data.u1_size, |
| u1_min_tu_size, |
| u1_max_tu_size, |
| u1_is_skip); |
| |
| ihevce_tuSplitArray_to_tuTree_mapper( |
| ps_root->ps_child_node_bl, |
| ai4_tuSplitArray, |
| u1_cu_size, |
| ps_root->ps_child_node_bl->s_luma_data.u1_size, |
| u1_min_tu_size, |
| u1_max_tu_size, |
| u1_is_skip); |
| |
| ihevce_tuSplitArray_to_tuTree_mapper( |
| ps_root->ps_child_node_br, |
| ai4_tuSplitArray, |
| u1_cu_size, |
| ps_root->ps_child_node_br->s_luma_data.u1_size, |
| u1_min_tu_size, |
| u1_max_tu_size, |
| u1_is_skip); |
| } |
| else |
| { |
| ps_root->ps_child_node_tl = NULL; |
| ps_root->ps_child_node_tr = NULL; |
| ps_root->ps_child_node_bl = NULL; |
| ps_root->ps_child_node_br = NULL; |
| } |
| } |