You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2666 lines
94 KiB
2666 lines
94 KiB
/******************************************************************************
|
|
*
|
|
* 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;
|
|
}
|
|
}
|