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.

4756 lines
171 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 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_multi_thrd_funcs.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_bs_compute_ctb.h"
#include "ihevce_global_tables.h"
#include "ihevce_dep_mngr_interface.h"
#include "hme_datatype.h"
#include "hme_interface.h"
#include "hme_common_defs.h"
#include "hme_defs.h"
#include "ihevce_me_instr_set_router.h"
#include "hme_globals.h"
#include "hme_utils.h"
#include "hme_coarse.h"
#include "hme_refine.h"
#include "hme_err_compute.h"
#include "hme_common_utils.h"
#include "hme_search_algo.h"
#include "ihevce_profile.h"
/*****************************************************************************/
/* Function Definitions */
/*****************************************************************************/
void hme_init_globals()
{
GRID_PT_T id;
S32 i, j;
/*************************************************************************/
/* Initialize the lookup table for x offset, y offset, optimized mask */
/* based on grid id. The design is as follows: */
/* */
/* a b c d */
/* TL T TR e */
/* L C R f */
/* BL B BR */
/* */
/* IF a non corner pt, like T is the new minima, then we need to */
/* evaluate only 3 new pts, in this case, a, b, c. So the optimal */
/* grid mask would reflect this. If a corner pt like TR is the new */
/* minima, then we need to evaluate 5 new pts, in this case, b, c, d, */
/* e and f. So the grid mask will have 5 pts enabled. */
/*************************************************************************/
id = PT_C;
gai4_opt_grid_mask[id] = GRID_ALL_PTS_VALID ^ (BIT_EN(PT_C));
gai1_grid_id_to_x[id] = 0;
gai1_grid_id_to_y[id] = 0;
gai4_opt_grid_mask_diamond[id] = GRID_DIAMOND_ENABLE_ALL ^ (BIT_EN(PT_C));
gai4_opt_grid_mask_conventional[id] = GRID_ALL_PTS_VALID ^ (BIT_EN(PT_C));
id = PT_L;
gai4_opt_grid_mask[id] = BIT_EN(PT_TL) | BIT_EN(PT_L) | BIT_EN(PT_BL);
gai1_grid_id_to_x[id] = -1;
gai1_grid_id_to_y[id] = 0;
gai4_opt_grid_mask_diamond[id] = BIT_EN(PT_T) | BIT_EN(PT_L) | BIT_EN(PT_B);
gai4_opt_grid_mask_conventional[id] = BIT_EN(PT_T) | BIT_EN(PT_L) | BIT_EN(PT_B);
id = PT_R;
gai4_opt_grid_mask[id] = BIT_EN(PT_TR) | BIT_EN(PT_R) | BIT_EN(PT_BR);
gai1_grid_id_to_x[id] = 1;
gai1_grid_id_to_y[id] = 0;
gai4_opt_grid_mask_diamond[id] = BIT_EN(PT_T) | BIT_EN(PT_R) | BIT_EN(PT_B);
gai4_opt_grid_mask_conventional[id] = BIT_EN(PT_T) | BIT_EN(PT_R) | BIT_EN(PT_B);
id = PT_T;
gai4_opt_grid_mask[id] = BIT_EN(PT_TL) | BIT_EN(PT_T) | BIT_EN(PT_TR);
gai1_grid_id_to_x[id] = 0;
gai1_grid_id_to_y[id] = -1;
gai4_opt_grid_mask_diamond[id] = BIT_EN(PT_R) | BIT_EN(PT_L) | BIT_EN(PT_T);
gai4_opt_grid_mask_conventional[id] = BIT_EN(PT_R) | BIT_EN(PT_L) | BIT_EN(PT_T);
id = PT_B;
gai4_opt_grid_mask[id] = BIT_EN(PT_BL) | BIT_EN(PT_B) | BIT_EN(PT_BR);
gai1_grid_id_to_x[id] = 0;
gai1_grid_id_to_y[id] = 1;
gai4_opt_grid_mask_diamond[id] = BIT_EN(PT_B) | BIT_EN(PT_L) | BIT_EN(PT_R);
gai4_opt_grid_mask_conventional[id] = BIT_EN(PT_B) | BIT_EN(PT_L) | BIT_EN(PT_R);
id = PT_TL;
gai4_opt_grid_mask[id] = gai4_opt_grid_mask[PT_L] | gai4_opt_grid_mask[PT_T];
gai1_grid_id_to_x[id] = -1;
gai1_grid_id_to_y[id] = -1;
gai4_opt_grid_mask_conventional[id] = BIT_EN(PT_T) | BIT_EN(PT_L);
id = PT_TR;
gai4_opt_grid_mask[id] = gai4_opt_grid_mask[PT_R] | gai4_opt_grid_mask[PT_T];
gai1_grid_id_to_x[id] = 1;
gai1_grid_id_to_y[id] = -1;
gai4_opt_grid_mask_conventional[id] = BIT_EN(PT_T) | BIT_EN(PT_R);
id = PT_BL;
gai4_opt_grid_mask[id] = gai4_opt_grid_mask[PT_L] | gai4_opt_grid_mask[PT_B];
gai1_grid_id_to_x[id] = -1;
gai1_grid_id_to_y[id] = 1;
gai4_opt_grid_mask_conventional[id] = BIT_EN(PT_L) | BIT_EN(PT_B);
id = PT_BR;
gai4_opt_grid_mask[id] = gai4_opt_grid_mask[PT_R] | gai4_opt_grid_mask[PT_B];
gai1_grid_id_to_x[id] = 1;
gai1_grid_id_to_y[id] = 1;
gai4_opt_grid_mask_conventional[id] = BIT_EN(PT_R) | BIT_EN(PT_B);
ge_part_id_to_blk_size[CU_8x8][PART_ID_2Nx2N] = BLK_8x8;
ge_part_id_to_blk_size[CU_8x8][PART_ID_2NxN_T] = BLK_8x4;
ge_part_id_to_blk_size[CU_8x8][PART_ID_2NxN_B] = BLK_8x4;
ge_part_id_to_blk_size[CU_8x8][PART_ID_Nx2N_L] = BLK_4x8;
ge_part_id_to_blk_size[CU_8x8][PART_ID_Nx2N_R] = BLK_4x8;
ge_part_id_to_blk_size[CU_8x8][PART_ID_NxN_TL] = BLK_4x4;
ge_part_id_to_blk_size[CU_8x8][PART_ID_NxN_TR] = BLK_4x4;
ge_part_id_to_blk_size[CU_8x8][PART_ID_NxN_BL] = BLK_4x4;
ge_part_id_to_blk_size[CU_8x8][PART_ID_NxN_BR] = BLK_4x4;
ge_part_id_to_blk_size[CU_8x8][PART_ID_2NxnU_T] = BLK_INVALID;
ge_part_id_to_blk_size[CU_8x8][PART_ID_2NxnU_B] = BLK_INVALID;
ge_part_id_to_blk_size[CU_8x8][PART_ID_2NxnD_T] = BLK_INVALID;
ge_part_id_to_blk_size[CU_8x8][PART_ID_2NxnD_B] = BLK_INVALID;
ge_part_id_to_blk_size[CU_8x8][PART_ID_nLx2N_L] = BLK_INVALID;
ge_part_id_to_blk_size[CU_8x8][PART_ID_nLx2N_R] = BLK_INVALID;
ge_part_id_to_blk_size[CU_8x8][PART_ID_nRx2N_L] = BLK_INVALID;
ge_part_id_to_blk_size[CU_8x8][PART_ID_nRx2N_R] = BLK_INVALID;
ge_part_id_to_blk_size[CU_16x16][PART_ID_2Nx2N] = BLK_16x16;
ge_part_id_to_blk_size[CU_16x16][PART_ID_2NxN_T] = BLK_16x8;
ge_part_id_to_blk_size[CU_16x16][PART_ID_2NxN_B] = BLK_16x8;
ge_part_id_to_blk_size[CU_16x16][PART_ID_Nx2N_L] = BLK_8x16;
ge_part_id_to_blk_size[CU_16x16][PART_ID_Nx2N_R] = BLK_8x16;
ge_part_id_to_blk_size[CU_16x16][PART_ID_NxN_TL] = BLK_8x8;
ge_part_id_to_blk_size[CU_16x16][PART_ID_NxN_TR] = BLK_8x8;
ge_part_id_to_blk_size[CU_16x16][PART_ID_NxN_BL] = BLK_8x8;
ge_part_id_to_blk_size[CU_16x16][PART_ID_NxN_BR] = BLK_8x8;
ge_part_id_to_blk_size[CU_16x16][PART_ID_2NxnU_T] = BLK_16x4;
ge_part_id_to_blk_size[CU_16x16][PART_ID_2NxnU_B] = BLK_16x12;
ge_part_id_to_blk_size[CU_16x16][PART_ID_2NxnD_T] = BLK_16x12;
ge_part_id_to_blk_size[CU_16x16][PART_ID_2NxnD_B] = BLK_16x4;
ge_part_id_to_blk_size[CU_16x16][PART_ID_nLx2N_L] = BLK_4x16;
ge_part_id_to_blk_size[CU_16x16][PART_ID_nLx2N_R] = BLK_12x16;
ge_part_id_to_blk_size[CU_16x16][PART_ID_nRx2N_L] = BLK_12x16;
ge_part_id_to_blk_size[CU_16x16][PART_ID_nRx2N_R] = BLK_4x16;
ge_part_id_to_blk_size[CU_32x32][PART_ID_2Nx2N] = BLK_32x32;
ge_part_id_to_blk_size[CU_32x32][PART_ID_2NxN_T] = BLK_32x16;
ge_part_id_to_blk_size[CU_32x32][PART_ID_2NxN_B] = BLK_32x16;
ge_part_id_to_blk_size[CU_32x32][PART_ID_Nx2N_L] = BLK_16x32;
ge_part_id_to_blk_size[CU_32x32][PART_ID_Nx2N_R] = BLK_16x32;
ge_part_id_to_blk_size[CU_32x32][PART_ID_NxN_TL] = BLK_16x16;
ge_part_id_to_blk_size[CU_32x32][PART_ID_NxN_TR] = BLK_16x16;
ge_part_id_to_blk_size[CU_32x32][PART_ID_NxN_BL] = BLK_16x16;
ge_part_id_to_blk_size[CU_32x32][PART_ID_NxN_BR] = BLK_16x16;
ge_part_id_to_blk_size[CU_32x32][PART_ID_2NxnU_T] = BLK_32x8;
ge_part_id_to_blk_size[CU_32x32][PART_ID_2NxnU_B] = BLK_32x24;
ge_part_id_to_blk_size[CU_32x32][PART_ID_2NxnD_T] = BLK_32x24;
ge_part_id_to_blk_size[CU_32x32][PART_ID_2NxnD_B] = BLK_32x8;
ge_part_id_to_blk_size[CU_32x32][PART_ID_nLx2N_L] = BLK_8x32;
ge_part_id_to_blk_size[CU_32x32][PART_ID_nLx2N_R] = BLK_24x32;
ge_part_id_to_blk_size[CU_32x32][PART_ID_nRx2N_L] = BLK_24x32;
ge_part_id_to_blk_size[CU_32x32][PART_ID_nRx2N_R] = BLK_8x32;
ge_part_id_to_blk_size[CU_64x64][PART_ID_2Nx2N] = BLK_64x64;
ge_part_id_to_blk_size[CU_64x64][PART_ID_2NxN_T] = BLK_64x32;
ge_part_id_to_blk_size[CU_64x64][PART_ID_2NxN_B] = BLK_64x32;
ge_part_id_to_blk_size[CU_64x64][PART_ID_Nx2N_L] = BLK_32x64;
ge_part_id_to_blk_size[CU_64x64][PART_ID_Nx2N_R] = BLK_32x64;
ge_part_id_to_blk_size[CU_64x64][PART_ID_NxN_TL] = BLK_32x32;
ge_part_id_to_blk_size[CU_64x64][PART_ID_NxN_TR] = BLK_32x32;
ge_part_id_to_blk_size[CU_64x64][PART_ID_NxN_BL] = BLK_32x32;
ge_part_id_to_blk_size[CU_64x64][PART_ID_NxN_BR] = BLK_32x32;
ge_part_id_to_blk_size[CU_64x64][PART_ID_2NxnU_T] = BLK_64x16;
ge_part_id_to_blk_size[CU_64x64][PART_ID_2NxnU_B] = BLK_64x48;
ge_part_id_to_blk_size[CU_64x64][PART_ID_2NxnD_T] = BLK_64x48;
ge_part_id_to_blk_size[CU_64x64][PART_ID_2NxnD_B] = BLK_64x16;
ge_part_id_to_blk_size[CU_64x64][PART_ID_nLx2N_L] = BLK_16x64;
ge_part_id_to_blk_size[CU_64x64][PART_ID_nLx2N_R] = BLK_48x64;
ge_part_id_to_blk_size[CU_64x64][PART_ID_nRx2N_L] = BLK_48x64;
ge_part_id_to_blk_size[CU_64x64][PART_ID_nRx2N_R] = BLK_16x64;
gau1_num_parts_in_part_type[PRT_2Nx2N] = 1;
gau1_num_parts_in_part_type[PRT_2NxN] = 2;
gau1_num_parts_in_part_type[PRT_Nx2N] = 2;
gau1_num_parts_in_part_type[PRT_NxN] = 4;
gau1_num_parts_in_part_type[PRT_2NxnU] = 2;
gau1_num_parts_in_part_type[PRT_2NxnD] = 2;
gau1_num_parts_in_part_type[PRT_nLx2N] = 2;
gau1_num_parts_in_part_type[PRT_nRx2N] = 2;
for(i = 0; i < MAX_PART_TYPES; i++)
for(j = 0; j < MAX_NUM_PARTS; j++)
ge_part_type_to_part_id[i][j] = PART_ID_INVALID;
/* 2Nx2N only one partition */
ge_part_type_to_part_id[PRT_2Nx2N][0] = PART_ID_2Nx2N;
/* 2NxN 2 partitions */
ge_part_type_to_part_id[PRT_2NxN][0] = PART_ID_2NxN_T;
ge_part_type_to_part_id[PRT_2NxN][1] = PART_ID_2NxN_B;
/* Nx2N 2 partitions */
ge_part_type_to_part_id[PRT_Nx2N][0] = PART_ID_Nx2N_L;
ge_part_type_to_part_id[PRT_Nx2N][1] = PART_ID_Nx2N_R;
/* NxN 4 partitions */
ge_part_type_to_part_id[PRT_NxN][0] = PART_ID_NxN_TL;
ge_part_type_to_part_id[PRT_NxN][1] = PART_ID_NxN_TR;
ge_part_type_to_part_id[PRT_NxN][2] = PART_ID_NxN_BL;
ge_part_type_to_part_id[PRT_NxN][3] = PART_ID_NxN_BR;
/* AMP 2Nx (N/2 + 3N/2) 2 partitions */
ge_part_type_to_part_id[PRT_2NxnU][0] = PART_ID_2NxnU_T;
ge_part_type_to_part_id[PRT_2NxnU][1] = PART_ID_2NxnU_B;
/* AMP 2Nx (3N/2 + N/2) 2 partitions */
ge_part_type_to_part_id[PRT_2NxnD][0] = PART_ID_2NxnD_T;
ge_part_type_to_part_id[PRT_2NxnD][1] = PART_ID_2NxnD_B;
/* AMP (N/2 + 3N/2) x 2N 2 partitions */
ge_part_type_to_part_id[PRT_nLx2N][0] = PART_ID_nLx2N_L;
ge_part_type_to_part_id[PRT_nLx2N][1] = PART_ID_nLx2N_R;
/* AMP (3N/2 + N/2) x 2N 2 partitions */
ge_part_type_to_part_id[PRT_nRx2N][0] = PART_ID_nRx2N_L;
ge_part_type_to_part_id[PRT_nRx2N][1] = PART_ID_nRx2N_R;
/*************************************************************************/
/* initialize attributes for each partition id within the cu. */
/*************************************************************************/
{
part_attr_t *ps_part_attr;
ps_part_attr = &gas_part_attr_in_cu[PART_ID_2Nx2N];
ps_part_attr->u1_x_start = 0;
ps_part_attr->u1_y_start = 0;
ps_part_attr->u1_x_count = 8;
ps_part_attr->u1_y_count = 8;
ps_part_attr = &gas_part_attr_in_cu[PART_ID_2NxN_T];
ps_part_attr->u1_x_start = 0;
ps_part_attr->u1_y_start = 0;
ps_part_attr->u1_x_count = 8;
ps_part_attr->u1_y_count = 4;
ps_part_attr = &gas_part_attr_in_cu[PART_ID_2NxN_B];
ps_part_attr->u1_x_start = 0;
ps_part_attr->u1_y_start = 4;
ps_part_attr->u1_x_count = 8;
ps_part_attr->u1_y_count = 4;
ps_part_attr = &gas_part_attr_in_cu[PART_ID_Nx2N_L];
ps_part_attr->u1_x_start = 0;
ps_part_attr->u1_y_start = 0;
ps_part_attr->u1_x_count = 4;
ps_part_attr->u1_y_count = 8;
ps_part_attr = &gas_part_attr_in_cu[PART_ID_Nx2N_R];
ps_part_attr->u1_x_start = 4;
ps_part_attr->u1_y_start = 0;
ps_part_attr->u1_x_count = 4;
ps_part_attr->u1_y_count = 8;
ps_part_attr = &gas_part_attr_in_cu[PART_ID_NxN_TL];
ps_part_attr->u1_x_start = 0;
ps_part_attr->u1_y_start = 0;
ps_part_attr->u1_x_count = 4;
ps_part_attr->u1_y_count = 4;
ps_part_attr = &gas_part_attr_in_cu[PART_ID_NxN_TR];
ps_part_attr->u1_x_start = 4;
ps_part_attr->u1_y_start = 0;
ps_part_attr->u1_x_count = 4;
ps_part_attr->u1_y_count = 4;
ps_part_attr = &gas_part_attr_in_cu[PART_ID_NxN_BL];
ps_part_attr->u1_x_start = 0;
ps_part_attr->u1_y_start = 4;
ps_part_attr->u1_x_count = 4;
ps_part_attr->u1_y_count = 4;
ps_part_attr = &gas_part_attr_in_cu[PART_ID_NxN_BR];
ps_part_attr->u1_x_start = 4;
ps_part_attr->u1_y_start = 4;
ps_part_attr->u1_x_count = 4;
ps_part_attr->u1_y_count = 4;
ps_part_attr = &gas_part_attr_in_cu[PART_ID_2NxnU_T];
ps_part_attr->u1_x_start = 0;
ps_part_attr->u1_y_start = 0;
ps_part_attr->u1_x_count = 8;
ps_part_attr->u1_y_count = 2;
ps_part_attr = &gas_part_attr_in_cu[PART_ID_2NxnU_B];
ps_part_attr->u1_x_start = 0;
ps_part_attr->u1_y_start = 2;
ps_part_attr->u1_x_count = 8;
ps_part_attr->u1_y_count = 6;
ps_part_attr = &gas_part_attr_in_cu[PART_ID_2NxnD_T];
ps_part_attr->u1_x_start = 0;
ps_part_attr->u1_y_start = 0;
ps_part_attr->u1_x_count = 8;
ps_part_attr->u1_y_count = 6;
ps_part_attr = &gas_part_attr_in_cu[PART_ID_2NxnD_B];
ps_part_attr->u1_x_start = 0;
ps_part_attr->u1_y_start = 6;
ps_part_attr->u1_x_count = 8;
ps_part_attr->u1_y_count = 2;
ps_part_attr = &gas_part_attr_in_cu[PART_ID_nLx2N_L];
ps_part_attr->u1_x_start = 0;
ps_part_attr->u1_y_start = 0;
ps_part_attr->u1_x_count = 2;
ps_part_attr->u1_y_count = 8;
ps_part_attr = &gas_part_attr_in_cu[PART_ID_nLx2N_R];
ps_part_attr->u1_x_start = 2;
ps_part_attr->u1_y_start = 0;
ps_part_attr->u1_x_count = 6;
ps_part_attr->u1_y_count = 8;
ps_part_attr = &gas_part_attr_in_cu[PART_ID_nRx2N_L];
ps_part_attr->u1_x_start = 0;
ps_part_attr->u1_y_start = 0;
ps_part_attr->u1_x_count = 6;
ps_part_attr->u1_y_count = 8;
ps_part_attr = &gas_part_attr_in_cu[PART_ID_nRx2N_R];
ps_part_attr->u1_x_start = 6;
ps_part_attr->u1_y_start = 0;
ps_part_attr->u1_x_count = 2;
ps_part_attr->u1_y_count = 8;
}
for(i = 0; i < NUM_BLK_SIZES; i++)
ge_blk_size_to_cu_size[i] = CU_INVALID;
ge_blk_size_to_cu_size[BLK_8x8] = CU_8x8;
ge_blk_size_to_cu_size[BLK_16x16] = CU_16x16;
ge_blk_size_to_cu_size[BLK_32x32] = CU_32x32;
ge_blk_size_to_cu_size[BLK_64x64] = CU_64x64;
/* This is the reverse, given cU size, get blk size */
ge_cu_size_to_blk_size[CU_8x8] = BLK_8x8;
ge_cu_size_to_blk_size[CU_16x16] = BLK_16x16;
ge_cu_size_to_blk_size[CU_32x32] = BLK_32x32;
ge_cu_size_to_blk_size[CU_64x64] = BLK_64x64;
gau1_is_vert_part[PRT_2Nx2N] = 0;
gau1_is_vert_part[PRT_2NxN] = 0;
gau1_is_vert_part[PRT_Nx2N] = 1;
gau1_is_vert_part[PRT_NxN] = 1;
gau1_is_vert_part[PRT_2NxnU] = 0;
gau1_is_vert_part[PRT_2NxnD] = 0;
gau1_is_vert_part[PRT_nLx2N] = 1;
gau1_is_vert_part[PRT_nRx2N] = 1;
/* Initialise the number of best results for the full pell refinement */
gau1_num_best_results_PQ[PART_ID_2Nx2N] = 2;
gau1_num_best_results_PQ[PART_ID_2NxN_T] = 0;
gau1_num_best_results_PQ[PART_ID_2NxN_B] = 0;
gau1_num_best_results_PQ[PART_ID_Nx2N_L] = 0;
gau1_num_best_results_PQ[PART_ID_Nx2N_R] = 0;
gau1_num_best_results_PQ[PART_ID_NxN_TL] = 1;
gau1_num_best_results_PQ[PART_ID_NxN_TR] = 1;
gau1_num_best_results_PQ[PART_ID_NxN_BL] = 1;
gau1_num_best_results_PQ[PART_ID_NxN_BR] = 1;
gau1_num_best_results_PQ[PART_ID_2NxnU_T] = 1;
gau1_num_best_results_PQ[PART_ID_2NxnU_B] = 0;
gau1_num_best_results_PQ[PART_ID_2NxnD_T] = 0;
gau1_num_best_results_PQ[PART_ID_2NxnD_B] = 1;
gau1_num_best_results_PQ[PART_ID_nLx2N_L] = 1;
gau1_num_best_results_PQ[PART_ID_nLx2N_R] = 0;
gau1_num_best_results_PQ[PART_ID_nRx2N_L] = 0;
gau1_num_best_results_PQ[PART_ID_nRx2N_R] = 1;
gau1_num_best_results_HQ[PART_ID_2Nx2N] = 2;
gau1_num_best_results_HQ[PART_ID_2NxN_T] = 0;
gau1_num_best_results_HQ[PART_ID_2NxN_B] = 0;
gau1_num_best_results_HQ[PART_ID_Nx2N_L] = 0;
gau1_num_best_results_HQ[PART_ID_Nx2N_R] = 0;
gau1_num_best_results_HQ[PART_ID_NxN_TL] = 1;
gau1_num_best_results_HQ[PART_ID_NxN_TR] = 1;
gau1_num_best_results_HQ[PART_ID_NxN_BL] = 1;
gau1_num_best_results_HQ[PART_ID_NxN_BR] = 1;
gau1_num_best_results_HQ[PART_ID_2NxnU_T] = 1;
gau1_num_best_results_HQ[PART_ID_2NxnU_B] = 0;
gau1_num_best_results_HQ[PART_ID_2NxnD_T] = 0;
gau1_num_best_results_HQ[PART_ID_2NxnD_B] = 1;
gau1_num_best_results_HQ[PART_ID_nLx2N_L] = 1;
gau1_num_best_results_HQ[PART_ID_nLx2N_R] = 0;
gau1_num_best_results_HQ[PART_ID_nRx2N_L] = 0;
gau1_num_best_results_HQ[PART_ID_nRx2N_R] = 1;
gau1_num_best_results_MS[PART_ID_2Nx2N] = 2;
gau1_num_best_results_MS[PART_ID_2NxN_T] = 0;
gau1_num_best_results_MS[PART_ID_2NxN_B] = 0;
gau1_num_best_results_MS[PART_ID_Nx2N_L] = 0;
gau1_num_best_results_MS[PART_ID_Nx2N_R] = 0;
gau1_num_best_results_MS[PART_ID_NxN_TL] = 1;
gau1_num_best_results_MS[PART_ID_NxN_TR] = 1;
gau1_num_best_results_MS[PART_ID_NxN_BL] = 1;
gau1_num_best_results_MS[PART_ID_NxN_BR] = 1;
gau1_num_best_results_MS[PART_ID_2NxnU_T] = 1;
gau1_num_best_results_MS[PART_ID_2NxnU_B] = 0;
gau1_num_best_results_MS[PART_ID_2NxnD_T] = 0;
gau1_num_best_results_MS[PART_ID_2NxnD_B] = 1;
gau1_num_best_results_MS[PART_ID_nLx2N_L] = 1;
gau1_num_best_results_MS[PART_ID_nLx2N_R] = 0;
gau1_num_best_results_MS[PART_ID_nRx2N_L] = 0;
gau1_num_best_results_MS[PART_ID_nRx2N_R] = 1;
gau1_num_best_results_HS[PART_ID_2Nx2N] = 2;
gau1_num_best_results_HS[PART_ID_2NxN_T] = 0;
gau1_num_best_results_HS[PART_ID_2NxN_B] = 0;
gau1_num_best_results_HS[PART_ID_Nx2N_L] = 0;
gau1_num_best_results_HS[PART_ID_Nx2N_R] = 0;
gau1_num_best_results_HS[PART_ID_NxN_TL] = 0;
gau1_num_best_results_HS[PART_ID_NxN_TR] = 0;
gau1_num_best_results_HS[PART_ID_NxN_BL] = 0;
gau1_num_best_results_HS[PART_ID_NxN_BR] = 0;
gau1_num_best_results_HS[PART_ID_2NxnU_T] = 0;
gau1_num_best_results_HS[PART_ID_2NxnU_B] = 0;
gau1_num_best_results_HS[PART_ID_2NxnD_T] = 0;
gau1_num_best_results_HS[PART_ID_2NxnD_B] = 0;
gau1_num_best_results_HS[PART_ID_nLx2N_L] = 0;
gau1_num_best_results_HS[PART_ID_nLx2N_R] = 0;
gau1_num_best_results_HS[PART_ID_nRx2N_L] = 0;
gau1_num_best_results_HS[PART_ID_nRx2N_R] = 0;
gau1_num_best_results_XS[PART_ID_2Nx2N] = 2;
gau1_num_best_results_XS[PART_ID_2NxN_T] = 0;
gau1_num_best_results_XS[PART_ID_2NxN_B] = 0;
gau1_num_best_results_XS[PART_ID_Nx2N_L] = 0;
gau1_num_best_results_XS[PART_ID_Nx2N_R] = 0;
gau1_num_best_results_XS[PART_ID_NxN_TL] = 0;
gau1_num_best_results_XS[PART_ID_NxN_TR] = 0;
gau1_num_best_results_XS[PART_ID_NxN_BL] = 0;
gau1_num_best_results_XS[PART_ID_NxN_BR] = 0;
gau1_num_best_results_XS[PART_ID_2NxnU_T] = 0;
gau1_num_best_results_XS[PART_ID_2NxnU_B] = 0;
gau1_num_best_results_XS[PART_ID_2NxnD_T] = 0;
gau1_num_best_results_XS[PART_ID_2NxnD_B] = 0;
gau1_num_best_results_XS[PART_ID_nLx2N_L] = 0;
gau1_num_best_results_XS[PART_ID_nLx2N_R] = 0;
gau1_num_best_results_XS[PART_ID_nRx2N_L] = 0;
gau1_num_best_results_XS[PART_ID_nRx2N_R] = 0;
gau1_num_best_results_XS25[PART_ID_2Nx2N] = MAX_NUM_CANDS_FOR_FPEL_REFINE_IN_XS25;
gau1_num_best_results_XS25[PART_ID_2NxN_T] = 0;
gau1_num_best_results_XS25[PART_ID_2NxN_B] = 0;
gau1_num_best_results_XS25[PART_ID_Nx2N_L] = 0;
gau1_num_best_results_XS25[PART_ID_Nx2N_R] = 0;
gau1_num_best_results_XS25[PART_ID_NxN_TL] = 0;
gau1_num_best_results_XS25[PART_ID_NxN_TR] = 0;
gau1_num_best_results_XS25[PART_ID_NxN_BL] = 0;
gau1_num_best_results_XS25[PART_ID_NxN_BR] = 0;
gau1_num_best_results_XS25[PART_ID_2NxnU_T] = 0;
gau1_num_best_results_XS25[PART_ID_2NxnU_B] = 0;
gau1_num_best_results_XS25[PART_ID_2NxnD_T] = 0;
gau1_num_best_results_XS25[PART_ID_2NxnD_B] = 0;
gau1_num_best_results_XS25[PART_ID_nLx2N_L] = 0;
gau1_num_best_results_XS25[PART_ID_nLx2N_R] = 0;
gau1_num_best_results_XS25[PART_ID_nRx2N_L] = 0;
gau1_num_best_results_XS25[PART_ID_nRx2N_R] = 0;
/* Top right validity for each part id */
gau1_partid_tr_valid[PART_ID_2Nx2N] = 1;
gau1_partid_tr_valid[PART_ID_2NxN_T] = 1;
gau1_partid_tr_valid[PART_ID_2NxN_B] = 0;
gau1_partid_tr_valid[PART_ID_Nx2N_L] = 1;
gau1_partid_tr_valid[PART_ID_Nx2N_R] = 1;
gau1_partid_tr_valid[PART_ID_NxN_TL] = 1;
gau1_partid_tr_valid[PART_ID_NxN_TR] = 1;
gau1_partid_tr_valid[PART_ID_NxN_BL] = 1;
gau1_partid_tr_valid[PART_ID_NxN_BR] = 0;
gau1_partid_tr_valid[PART_ID_2NxnU_T] = 1;
gau1_partid_tr_valid[PART_ID_2NxnU_B] = 0;
gau1_partid_tr_valid[PART_ID_2NxnD_T] = 1;
gau1_partid_tr_valid[PART_ID_2NxnD_B] = 0;
gau1_partid_tr_valid[PART_ID_nLx2N_L] = 1;
gau1_partid_tr_valid[PART_ID_nLx2N_R] = 1;
gau1_partid_tr_valid[PART_ID_nRx2N_L] = 1;
gau1_partid_tr_valid[PART_ID_nRx2N_R] = 1;
/* Bot Left validity for each part id */
gau1_partid_bl_valid[PART_ID_2Nx2N] = 1;
gau1_partid_bl_valid[PART_ID_2NxN_T] = 1;
gau1_partid_bl_valid[PART_ID_2NxN_B] = 1;
gau1_partid_bl_valid[PART_ID_Nx2N_L] = 1;
gau1_partid_bl_valid[PART_ID_Nx2N_R] = 0;
gau1_partid_bl_valid[PART_ID_NxN_TL] = 1;
gau1_partid_bl_valid[PART_ID_NxN_TR] = 0;
gau1_partid_bl_valid[PART_ID_NxN_BL] = 1;
gau1_partid_bl_valid[PART_ID_NxN_BR] = 0;
gau1_partid_bl_valid[PART_ID_2NxnU_T] = 1;
gau1_partid_bl_valid[PART_ID_2NxnU_B] = 1;
gau1_partid_bl_valid[PART_ID_2NxnD_T] = 1;
gau1_partid_bl_valid[PART_ID_2NxnD_B] = 1;
gau1_partid_bl_valid[PART_ID_nLx2N_L] = 1;
gau1_partid_bl_valid[PART_ID_nLx2N_R] = 0;
gau1_partid_bl_valid[PART_ID_nRx2N_L] = 1;
gau1_partid_bl_valid[PART_ID_nRx2N_R] = 0;
/*Part id to part num of this partition id in the CU */
gau1_part_id_to_part_num[PART_ID_2Nx2N] = 0;
gau1_part_id_to_part_num[PART_ID_2NxN_T] = 0;
gau1_part_id_to_part_num[PART_ID_2NxN_B] = 1;
gau1_part_id_to_part_num[PART_ID_Nx2N_L] = 0;
gau1_part_id_to_part_num[PART_ID_Nx2N_R] = 1;
gau1_part_id_to_part_num[PART_ID_NxN_TL] = 0;
gau1_part_id_to_part_num[PART_ID_NxN_TR] = 1;
gau1_part_id_to_part_num[PART_ID_NxN_BL] = 2;
gau1_part_id_to_part_num[PART_ID_NxN_BR] = 3;
gau1_part_id_to_part_num[PART_ID_2NxnU_T] = 0;
gau1_part_id_to_part_num[PART_ID_2NxnU_B] = 1;
gau1_part_id_to_part_num[PART_ID_2NxnD_T] = 0;
gau1_part_id_to_part_num[PART_ID_2NxnD_B] = 1;
gau1_part_id_to_part_num[PART_ID_nLx2N_L] = 0;
gau1_part_id_to_part_num[PART_ID_nLx2N_R] = 1;
gau1_part_id_to_part_num[PART_ID_nRx2N_L] = 0;
gau1_part_id_to_part_num[PART_ID_nRx2N_R] = 1;
/*Which partition type does this partition id belong to */
ge_part_id_to_part_type[PART_ID_2Nx2N] = PRT_2Nx2N;
ge_part_id_to_part_type[PART_ID_2NxN_T] = PRT_2NxN;
ge_part_id_to_part_type[PART_ID_2NxN_B] = PRT_2NxN;
ge_part_id_to_part_type[PART_ID_Nx2N_L] = PRT_Nx2N;
ge_part_id_to_part_type[PART_ID_Nx2N_R] = PRT_Nx2N;
ge_part_id_to_part_type[PART_ID_NxN_TL] = PRT_NxN;
ge_part_id_to_part_type[PART_ID_NxN_TR] = PRT_NxN;
ge_part_id_to_part_type[PART_ID_NxN_BL] = PRT_NxN;
ge_part_id_to_part_type[PART_ID_NxN_BR] = PRT_NxN;
ge_part_id_to_part_type[PART_ID_2NxnU_T] = PRT_2NxnU;
ge_part_id_to_part_type[PART_ID_2NxnU_B] = PRT_2NxnU;
ge_part_id_to_part_type[PART_ID_2NxnD_T] = PRT_2NxnD;
ge_part_id_to_part_type[PART_ID_2NxnD_B] = PRT_2NxnD;
ge_part_id_to_part_type[PART_ID_nLx2N_L] = PRT_nLx2N;
ge_part_id_to_part_type[PART_ID_nLx2N_R] = PRT_nLx2N;
ge_part_id_to_part_type[PART_ID_nRx2N_L] = PRT_nRx2N;
ge_part_id_to_part_type[PART_ID_nRx2N_R] = PRT_nRx2N;
/*************************************************************************/
/* Set up the bits to be taken up for the part type. This is equally */
/* divided up between the various partitions in the part-type. */
/* For NxN @ CU 16x16, we assume it as CU 8x8, so consider it as */
/* partition 2Nx2N. */
/*************************************************************************/
/* 1 bit for 2Nx2N partition */
gau1_bits_for_part_id_q1[PART_ID_2Nx2N] = 2;
/* 3 bits for symmetric part types, so 1.5 bits per partition */
gau1_bits_for_part_id_q1[PART_ID_2NxN_T] = 3;
gau1_bits_for_part_id_q1[PART_ID_2NxN_B] = 3;
gau1_bits_for_part_id_q1[PART_ID_Nx2N_L] = 3;
gau1_bits_for_part_id_q1[PART_ID_Nx2N_R] = 3;
/* 1 bit for NxN partitions, assuming these to be 2Nx2N CUs of lower level */
gau1_bits_for_part_id_q1[PART_ID_NxN_TL] = 2;
gau1_bits_for_part_id_q1[PART_ID_NxN_TR] = 2;
gau1_bits_for_part_id_q1[PART_ID_NxN_BL] = 2;
gau1_bits_for_part_id_q1[PART_ID_NxN_BR] = 2;
/* 4 bits for AMP so 2 bits per partition */
gau1_bits_for_part_id_q1[PART_ID_2NxnU_T] = 4;
gau1_bits_for_part_id_q1[PART_ID_2NxnU_B] = 4;
gau1_bits_for_part_id_q1[PART_ID_2NxnD_T] = 4;
gau1_bits_for_part_id_q1[PART_ID_2NxnD_B] = 4;
gau1_bits_for_part_id_q1[PART_ID_nLx2N_L] = 4;
gau1_bits_for_part_id_q1[PART_ID_nLx2N_R] = 4;
gau1_bits_for_part_id_q1[PART_ID_nRx2N_L] = 4;
gau1_bits_for_part_id_q1[PART_ID_nRx2N_R] = 4;
}
/**
********************************************************************************
* @fn hme_enc_num_alloc()
*
* @brief returns number of memtabs that is required by hme module
*
* @return Number of memtabs required
********************************************************************************
*/
S32 hme_enc_num_alloc(WORD32 i4_num_me_frm_pllel)
{
if(i4_num_me_frm_pllel > 1)
{
return ((S32)MAX_HME_ENC_TOT_MEMTABS);
}
else
{
return ((S32)MIN_HME_ENC_TOT_MEMTABS);
}
}
/**
********************************************************************************
* @fn hme_coarse_num_alloc()
*
* @brief returns number of memtabs that is required by hme module
*
* @return Number of memtabs required
********************************************************************************
*/
S32 hme_coarse_num_alloc()
{
return ((S32)HME_COARSE_TOT_MEMTABS);
}
/**
********************************************************************************
* @fn hme_coarse_dep_mngr_num_alloc()
*
* @brief returns number of memtabs that is required by Dep Mngr for hme module
*
* @return Number of memtabs required
********************************************************************************
*/
WORD32 hme_coarse_dep_mngr_num_alloc()
{
return ((WORD32)((MAX_NUM_HME_LAYERS - 1) * ihevce_dmgr_get_num_mem_recs()));
}
S32 hme_validate_init_prms(hme_init_prms_t *ps_prms)
{
S32 n_layers = ps_prms->num_simulcast_layers;
/* The final layer has got to be a non encode coarse layer */
if(n_layers > (MAX_NUM_LAYERS - 1))
return (-1);
if(n_layers < 1)
return (-1);
/* Width of the coarsest encode layer got to be >= 2*min_wd where min_Wd */
/* represents the min allowed width in any layer. Ditto with ht */
if(ps_prms->a_wd[n_layers - 1] < 2 * (MIN_WD_COARSE))
return (-1);
if(ps_prms->a_ht[n_layers - 1] < 2 * (MIN_HT_COARSE))
return (-1);
if(ps_prms->max_num_ref > MAX_NUM_REF)
return (-1);
if(ps_prms->max_num_ref < 0)
return (-1);
return (0);
}
void hme_set_layer_res_attrs(
layer_ctxt_t *ps_layer, S32 wd, S32 ht, S32 disp_wd, S32 disp_ht, U08 u1_enc)
{
ps_layer->i4_wd = wd;
ps_layer->i4_ht = ht;
ps_layer->i4_disp_wd = disp_wd;
ps_layer->i4_disp_ht = disp_ht;
if(0 == u1_enc)
{
ps_layer->i4_inp_stride = wd + 32 + 4;
ps_layer->i4_inp_offset = (ps_layer->i4_inp_stride * 16) + 16;
ps_layer->i4_pad_x_inp = 16;
ps_layer->i4_pad_y_inp = 16;
ps_layer->pu1_inp = ps_layer->pu1_inp_base + ps_layer->i4_inp_offset;
}
}
/**
********************************************************************************
* @fn hme_coarse_get_layer1_mv_bank_ref_idx_size()
*
* @brief returns the MV bank and ref idx size of Layer 1 (penultimate)
*
* @return none
********************************************************************************
*/
void hme_coarse_get_layer1_mv_bank_ref_idx_size(
S32 n_tot_layers,
S32 *a_wd,
S32 *a_ht,
S32 max_num_ref,
S32 *pi4_mv_bank_size,
S32 *pi4_ref_idx_size)
{
S32 num_blks, num_mvs_per_blk, num_ref;
S32 num_cols, num_rows, num_mvs_per_row;
S32 is_explicit_store = 1;
S32 wd, ht, num_layers_explicit_search;
S32 num_results, use_4x4;
wd = a_wd[1];
ht = a_ht[1];
/* Assuming abt 4 layers for 1080p, we do explicit search across all ref */
/* frames in all but final layer In final layer, it could be 1/2 */
//ps_hme_init_prms->num_layers_explicit_search = 3;
num_layers_explicit_search = 3;
if(num_layers_explicit_search <= 0)
num_layers_explicit_search = n_tot_layers - 1;
num_layers_explicit_search = MIN(num_layers_explicit_search, n_tot_layers - 1);
/* Possibly implicit search for lower (finer) layers */
if(n_tot_layers - 1 > num_layers_explicit_search)
is_explicit_store = 0;
/* coarsest layer alwasy uses 4x4 blks to store results */
if(1 == (n_tot_layers - 1))
{
/* we store 4 results in coarsest layer per blk. 8x4L, 8x4R, 4x8T, 4x8B */
//ps_hme_init_prms->max_num_results_coarse = 4;
//vijay : with new algo in coarseset layer this has to be revisited
num_results = 4;
}
else
{
/* Every refinement layer stores a max of 2 results per partition */
//ps_hme_init_prms->max_num_results = 2;
num_results = 2;
}
use_4x4 = hme_get_mv_blk_size(1, 1, n_tot_layers, 0);
num_cols = use_4x4 ? ((wd >> 2) + 2) : ((wd >> 3) + 2);
num_rows = use_4x4 ? ((ht >> 2) + 2) : ((ht >> 3) + 2);
if(is_explicit_store)
num_ref = max_num_ref;
else
num_ref = 2;
num_blks = num_cols * num_rows;
num_mvs_per_blk = num_ref * num_results;
num_mvs_per_row = num_mvs_per_blk * num_cols;
/* stroe the sizes */
*pi4_mv_bank_size = num_blks * num_mvs_per_blk * sizeof(hme_mv_t);
*pi4_ref_idx_size = num_blks * num_mvs_per_blk * sizeof(S08);
return;
}
/**
********************************************************************************
* @fn hme_alloc_init_layer_mv_bank()
*
* @brief memory alloc and init function for MV bank
*
* @return Number of memtabs required
********************************************************************************
*/
S32 hme_alloc_init_layer_mv_bank(
hme_memtab_t *ps_memtab,
S32 max_num_results,
S32 max_num_ref,
S32 use_4x4,
S32 mem_avail,
S32 u1_enc,
S32 wd,
S32 ht,
S32 is_explicit_store,
hme_mv_t **pps_mv_base,
S08 **pi1_ref_idx_base,
S32 *pi4_num_mvs_per_row)
{
S32 count = 0;
S32 size;
S32 num_blks, num_mvs_per_blk;
S32 num_ref;
S32 num_cols, num_rows, num_mvs_per_row;
if(is_explicit_store)
num_ref = max_num_ref;
else
num_ref = 2;
/* MV Bank allocation takes into consideration following */
/* number of results per reference x max num refrences is the amount */
/* bufffered up per blk. Numbero f blks in pic deps on the blk size, */
/* which could be either 4x4 or 8x8. */
num_cols = use_4x4 ? ((wd >> 2) + 2) : ((wd >> 3) + 2);
num_rows = use_4x4 ? ((ht >> 2) + 2) : ((ht >> 3) + 2);
if(u1_enc)
{
/* TODO: CTB64x64 is assumed. FIX according to actual CTB */
WORD32 num_ctb_cols = ((wd + 63) >> 6);
WORD32 num_ctb_rows = ((ht + 63) >> 6);
num_cols = (num_ctb_cols << 3) + 2;
num_rows = (num_ctb_rows << 3) + 2;
}
num_blks = num_cols * num_rows;
num_mvs_per_blk = num_ref * max_num_results;
num_mvs_per_row = num_mvs_per_blk * num_cols;
size = num_blks * num_mvs_per_blk * sizeof(hme_mv_t);
if(mem_avail)
{
/* store this for run time verifications */
*pi4_num_mvs_per_row = num_mvs_per_row;
ASSERT(ps_memtab[count].size == size);
*pps_mv_base = (hme_mv_t *)ps_memtab[count].pu1_mem;
}
else
{
ps_memtab[count].size = size;
ps_memtab[count].align = 4;
ps_memtab[count].e_mem_attr = HME_PERSISTENT_MEM;
}
count++;
/* Ref idx takes the same route as mvbase */
size = num_blks * num_mvs_per_blk * sizeof(S08);
if(mem_avail)
{
ASSERT(ps_memtab[count].size == size);
*pi1_ref_idx_base = (S08 *)ps_memtab[count].pu1_mem;
}
else
{
ps_memtab[count].size = size;
ps_memtab[count].align = 4;
ps_memtab[count].e_mem_attr = HME_PERSISTENT_MEM;
}
count++;
return (count);
}
/**
********************************************************************************
* @fn hme_alloc_init_layer()
*
* @brief memory alloc and init function
*
* @return Number of memtabs required
********************************************************************************
*/
S32 hme_alloc_init_layer(
hme_memtab_t *ps_memtab,
S32 max_num_results,
S32 max_num_ref,
S32 use_4x4,
S32 mem_avail,
S32 u1_enc,
S32 wd,
S32 ht,
S32 disp_wd,
S32 disp_ht,
S32 segment_layer,
S32 is_explicit_store,
layer_ctxt_t **pps_layer)
{
S32 count = 0;
layer_ctxt_t *ps_layer = NULL;
S32 size;
S32 num_ref;
ARG_NOT_USED(segment_layer);
if(is_explicit_store)
num_ref = max_num_ref;
else
num_ref = 2;
/* We do not store 4x4 results for encoding layers */
if(u1_enc)
use_4x4 = 0;
size = sizeof(layer_ctxt_t);
if(mem_avail)
{
ASSERT(ps_memtab[count].size == size);
ps_layer = (layer_ctxt_t *)ps_memtab[count].pu1_mem;
*pps_layer = ps_layer;
}
else
{
ps_memtab[count].size = size;
ps_memtab[count].align = 8;
ps_memtab[count].e_mem_attr = HME_PERSISTENT_MEM;
}
count++;
/* Input luma buffer allocated only for non encode case */
if(0 == u1_enc)
{
/* Allocate input with padding of 16 pixels */
size = (wd + 32 + 4) * (ht + 32 + 4);
if(mem_avail)
{
ASSERT(ps_memtab[count].size == size);
ps_layer->pu1_inp_base = ps_memtab[count].pu1_mem;
}
else
{
ps_memtab[count].size = size;
ps_memtab[count].align = 16;
ps_memtab[count].e_mem_attr = HME_PERSISTENT_MEM;
}
count++;
}
/* Allocate memory or just the layer mvbank strcture. */
/* TODO : see if this can be removed by moving it to layer_ctxt */
size = sizeof(layer_mv_t);
if(mem_avail)
{
ASSERT(ps_memtab[count].size == size);
ps_layer->ps_layer_mvbank = (layer_mv_t *)ps_memtab[count].pu1_mem;
}
else
{
ps_memtab[count].size = size;
ps_memtab[count].align = 8;
ps_memtab[count].e_mem_attr = HME_PERSISTENT_MEM;
}
count++;
if(mem_avail)
{
hme_set_layer_res_attrs(ps_layer, wd, ht, disp_wd, disp_ht, u1_enc);
}
return (count);
}
S32 hme_alloc_init_search_nodes(
search_results_t *ps_search_results,
hme_memtab_t *ps_memtabs,
S32 mem_avail,
S32 max_num_ref,
S32 max_num_results)
{
S32 size = max_num_results * sizeof(search_node_t) * max_num_ref * TOT_NUM_PARTS;
S32 j, k;
search_node_t *ps_search_node;
if(mem_avail == 0)
{
ps_memtabs->size = size;
ps_memtabs->align = 4;
ps_memtabs->e_mem_attr = HME_SCRATCH_OVLY_MEM;
return (1);
}
ps_search_node = (search_node_t *)ps_memtabs->pu1_mem;
ASSERT(ps_memtabs->size == size);
/****************************************************************************/
/* For each CU, we search and store N best results, per partition, per ref */
/* So, number of memtabs is num_refs * num_parts */
/****************************************************************************/
for(j = 0; j < max_num_ref; j++)
{
for(k = 0; k < TOT_NUM_PARTS; k++)
{
ps_search_results->aps_part_results[j][k] = ps_search_node;
ps_search_node += max_num_results;
}
}
return (1);
}
S32 hme_derive_num_layers(S32 n_enc_layers, S32 *p_wd, S32 *p_ht, S32 *p_disp_wd, S32 *p_disp_ht)
{
S32 i;
/* We keep downscaling by 2 till we hit one of the conditions: */
/* 1. MAX_NUM_LAYERS reached. */
/* 2. Width or ht goes below min width and ht allowed at coarsest layer */
ASSERT(n_enc_layers < MAX_NUM_LAYERS);
ASSERT(n_enc_layers > 0);
ASSERT(p_wd[0] <= HME_MAX_WIDTH);
ASSERT(p_ht[0] <= HME_MAX_HEIGHT);
p_disp_wd[0] = p_wd[0];
p_disp_ht[0] = p_ht[0];
/*************************************************************************/
/* Verify that for simulcast, lower layer to higher layer ratio is bet */
/* 2 (dyadic) and 1.33. Typically it should be 1.5. */
/* TODO : for interlace, we may choose to have additional downscaling for*/
/* width alone in coarsest layer to next layer. */
/*************************************************************************/
for(i = 1; i < n_enc_layers; i++)
{
S32 wd1, wd2, ht1, ht2;
wd1 = FLOOR16(p_wd[i - 1] >> 1);
wd2 = CEIL16((p_wd[i - 1] * 3) >> 2);
ASSERT(p_wd[i] >= wd1);
ASSERT(p_wd[i] <= wd2);
ht1 = FLOOR16(p_ht[i - 1] >> 1);
ht2 = CEIL16((p_ht[i - 1] * 3) >> 2);
ASSERT(p_ht[i] >= ht1);
ASSERT(p_ht[i] <= ht2);
}
ASSERT(p_wd[n_enc_layers - 1] >= 2 * MIN_WD_COARSE);
ASSERT(p_ht[n_enc_layers - 1] >= 2 * MIN_HT_COARSE);
for(i = n_enc_layers; i < MAX_NUM_LAYERS; i++)
{
if((p_wd[i - 1] < 2 * MIN_WD_COARSE) || (p_ht[i - 1] < 2 * MIN_HT_COARSE))
{
return (i);
}
/* Use CEIL16 to facilitate 16x16 searches in future, or to do */
/* segmentation study in future */
p_wd[i] = CEIL16(p_wd[i - 1] >> 1);
p_ht[i] = CEIL16(p_ht[i - 1] >> 1);
p_disp_wd[i] = p_disp_wd[i - 1] >> 1;
p_disp_ht[i] = p_disp_ht[i - 1] >> 1;
}
return (i);
}
/**
********************************************************************************
* @fn hme_get_mv_blk_size()
*
* @brief returns whether blk uses 4x4 size or something else.
*
* @param[in] enable_4x4 : input param from application to enable 4x4
*
* @param[in] layer_id : id of current layer (0 finest)
*
* @param[in] num_layeers : total num layers
*
* @param[in] is_enc : Whether encoding enabled for layer
*
* @return 1 for 4x4 blks, 0 for 8x8
********************************************************************************
*/
S32 hme_get_mv_blk_size(S32 enable_4x4, S32 layer_id, S32 num_layers, S32 is_enc)
{
S32 use_4x4 = enable_4x4;
if((layer_id <= 1) && (num_layers >= 4))
use_4x4 = USE_4x4_IN_L1;
if(layer_id == num_layers - 1)
use_4x4 = 1;
if(is_enc)
use_4x4 = 0;
return (use_4x4);
}
/**
********************************************************************************
* @fn hme_enc_alloc_init_mem()
*
* @brief Requests/ assign memory based on mem avail
*
* @param[in] ps_memtabs : memtab array
*
* @param[in] ps_prms : init prms
*
* @param[in] pv_ctxt : ME ctxt
*
* @param[in] mem_avail : request/assign flag
*
* @return 1 for 4x4 blks, 0 for 8x8
********************************************************************************
*/
S32 hme_enc_alloc_init_mem(
hme_memtab_t *ps_memtabs,
hme_init_prms_t *ps_prms,
void *pv_ctxt,
S32 mem_avail,
S32 i4_num_me_frm_pllel)
{
me_master_ctxt_t *ps_master_ctxt = (me_master_ctxt_t *)pv_ctxt;
me_ctxt_t *ps_ctxt;
S32 count = 0, size, i, j, use_4x4;
S32 n_tot_layers, n_enc_layers;
S32 num_layers_explicit_search;
S32 a_wd[MAX_NUM_LAYERS], a_ht[MAX_NUM_LAYERS];
S32 a_disp_wd[MAX_NUM_LAYERS], a_disp_ht[MAX_NUM_LAYERS];
S32 num_results;
S32 num_thrds;
S32 ctb_wd = 1 << ps_prms->log_ctb_size;
/* MV bank changes */
hme_mv_t *aps_mv_bank[((DEFAULT_MAX_REFERENCE_PICS << 1) * MAX_NUM_ME_PARALLEL) + 1] = { NULL };
S32 i4_num_mvs_per_row = 0;
S08 *api1_ref_idx[((DEFAULT_MAX_REFERENCE_PICS << 1) * MAX_NUM_ME_PARALLEL) + 1] = { NULL };
n_enc_layers = ps_prms->num_simulcast_layers;
/* Memtab 0: handle */
size = sizeof(me_master_ctxt_t);
if(mem_avail)
{
/* store the number of processing threads */
ps_master_ctxt->i4_num_proc_thrds = ps_prms->i4_num_proc_thrds;
}
else
{
ps_memtabs[count].size = size;
ps_memtabs[count].align = 8;
ps_memtabs[count].e_mem_attr = HME_PERSISTENT_MEM;
}
count++;
/* Memtab 1: ME threads ctxt */
size = ps_prms->i4_num_proc_thrds * sizeof(me_ctxt_t);
if(mem_avail)
{
me_ctxt_t *ps_me_tmp_ctxt = (me_ctxt_t *)ps_memtabs[count].pu1_mem;
/* store the indivisual thread ctxt pointers */
for(num_thrds = 0; num_thrds < ps_prms->i4_num_proc_thrds; num_thrds++)
{
ps_master_ctxt->aps_me_ctxt[num_thrds] = ps_me_tmp_ctxt++;
}
}
else
{
ps_memtabs[count].size = size;
ps_memtabs[count].align = 8;
ps_memtabs[count].e_mem_attr = HME_PERSISTENT_MEM;
}
count++;
/* Memtab 2: ME frame ctxts */
size = sizeof(me_frm_ctxt_t) * MAX_NUM_ME_PARALLEL * ps_prms->i4_num_proc_thrds;
if(mem_avail)
{
me_frm_ctxt_t *ps_me_frm_tmp_ctxt = (me_frm_ctxt_t *)ps_memtabs[count].pu1_mem;
for(i = 0; i < MAX_NUM_ME_PARALLEL; i++)
{
/* store the indivisual thread ctxt pointers */
for(num_thrds = 0; num_thrds < ps_prms->i4_num_proc_thrds; num_thrds++)
{
ps_master_ctxt->aps_me_ctxt[num_thrds]->aps_me_frm_prms[i] = ps_me_frm_tmp_ctxt;
ps_me_frm_tmp_ctxt++;
}
}
}
else
{
ps_memtabs[count].size = size;
ps_memtabs[count].align = 8;
ps_memtabs[count].e_mem_attr = HME_PERSISTENT_MEM;
}
count++;
memcpy(a_wd, ps_prms->a_wd, sizeof(S32) * ps_prms->num_simulcast_layers);
memcpy(a_ht, ps_prms->a_ht, sizeof(S32) * ps_prms->num_simulcast_layers);
/*************************************************************************/
/* Derive the number of HME layers, including both encoded and non encode*/
/* This function also derives the width and ht of each layer. */
/*************************************************************************/
n_tot_layers = hme_derive_num_layers(n_enc_layers, a_wd, a_ht, a_disp_wd, a_disp_ht);
num_layers_explicit_search = ps_prms->num_layers_explicit_search;
if(num_layers_explicit_search <= 0)
num_layers_explicit_search = n_tot_layers - 1;
num_layers_explicit_search = MIN(num_layers_explicit_search, n_tot_layers - 1);
if(mem_avail)
{
for(num_thrds = 0; num_thrds < ps_prms->i4_num_proc_thrds; num_thrds++)
{
me_frm_ctxt_t *ps_frm_ctxt;
ps_ctxt = ps_master_ctxt->aps_me_ctxt[num_thrds];
for(i = 0; i < MAX_NUM_ME_PARALLEL; i++)
{
ps_frm_ctxt = ps_ctxt->aps_me_frm_prms[i];
memset(ps_frm_ctxt->u1_encode, 0, n_tot_layers);
memset(ps_frm_ctxt->u1_encode, 1, n_enc_layers);
/* only one enocde layer is used */
ps_frm_ctxt->num_layers = 1;
ps_frm_ctxt->i4_wd = a_wd[0];
ps_frm_ctxt->i4_ht = a_ht[0];
/*
memcpy(ps_ctxt->a_wd, a_wd, sizeof(S32)*n_tot_layers);
memcpy(ps_ctxt->a_ht, a_ht, sizeof(S32)*n_tot_layers);
*/
ps_frm_ctxt->num_layers_explicit_search = num_layers_explicit_search;
ps_frm_ctxt->max_num_results = ps_prms->max_num_results;
ps_frm_ctxt->max_num_results_coarse = ps_prms->max_num_results_coarse;
ps_frm_ctxt->max_num_ref = ps_prms->max_num_ref;
}
}
}
/* Memtabs : Layers MV bank for encode layer */
/* Each ref_desr in master ctxt will have seperate layer ctxt */
for(i = 0; i < (ps_prms->max_num_ref * i4_num_me_frm_pllel) + 1; i++)
{
for(j = 0; j < 1; j++)
{
S32 is_explicit_store = 1;
S32 wd, ht;
U08 u1_enc = 1;
wd = a_wd[j];
ht = a_ht[j];
/* Possibly implicit search for lower (finer) layers */
if(n_tot_layers - j > num_layers_explicit_search)
is_explicit_store = 0;
/* Even if explicit search, we store only 2 results (L0 and L1) */
/* in finest layer */
if(j == 0)
{
is_explicit_store = 0;
}
/* coarsest layer alwasy uses 4x4 blks to store results */
if(j == n_tot_layers - 1)
{
num_results = ps_prms->max_num_results_coarse;
}
else
{
num_results = ps_prms->max_num_results;
if(j == 0)
num_results = 1;
}
use_4x4 = hme_get_mv_blk_size(ps_prms->use_4x4, j, n_tot_layers, u1_enc);
count += hme_alloc_init_layer_mv_bank(
&ps_memtabs[count],
num_results,
ps_prms->max_num_ref,
use_4x4,
mem_avail,
u1_enc,
wd,
ht,
is_explicit_store,
&aps_mv_bank[i],
&api1_ref_idx[i],
&i4_num_mvs_per_row);
}
}
/* Memtabs : Layers * num-ref + 1 */
for(i = 0; i < (ps_prms->max_num_ref * i4_num_me_frm_pllel) + 1; i++)
{
/* layer memory allocated only for enocde layer */
for(j = 0; j < 1; j++)
{
layer_ctxt_t *ps_layer;
S32 is_explicit_store = 1;
S32 segment_this_layer = (j == 0) ? 1 : ps_prms->segment_higher_layers;
S32 wd, ht;
U08 u1_enc = 1;
wd = a_wd[j];
ht = a_ht[j];
/* Possibly implicit search for lower (finer) layers */
if(n_tot_layers - j > num_layers_explicit_search)
is_explicit_store = 0;
/* Even if explicit search, we store only 2 results (L0 and L1) */
/* in finest layer */
if(j == 0)
{
is_explicit_store = 0;
}
/* coarsest layer alwasy uses 4x4 blks to store results */
if(j == n_tot_layers - 1)
{
num_results = ps_prms->max_num_results_coarse;
}
else
{
num_results = ps_prms->max_num_results;
if(j == 0)
num_results = 1;
}
use_4x4 = hme_get_mv_blk_size(ps_prms->use_4x4, j, n_tot_layers, u1_enc);
count += hme_alloc_init_layer(
&ps_memtabs[count],
num_results,
ps_prms->max_num_ref,
use_4x4,
mem_avail,
u1_enc,
wd,
ht,
a_disp_wd[j],
a_disp_ht[j],
segment_this_layer,
is_explicit_store,
&ps_layer);
if(mem_avail)
{
/* same ps_layer memory pointer is stored in all the threads */
for(num_thrds = 0; num_thrds < ps_prms->i4_num_proc_thrds; num_thrds++)
{
ps_ctxt = ps_master_ctxt->aps_me_ctxt[num_thrds];
ps_ctxt->as_ref_descr[i].aps_layers[j] = ps_layer;
}
/* store the MV bank pointers */
ps_layer->ps_layer_mvbank->max_num_mvs_per_row = i4_num_mvs_per_row;
ps_layer->ps_layer_mvbank->ps_mv_base = aps_mv_bank[i];
ps_layer->ps_layer_mvbank->pi1_ref_idx_base = api1_ref_idx[i];
}
}
}
/* Memtabs : Buf Mgr for predictor bufs and working mem */
/* TODO : Parameterise this appropriately */
size = MAX_WKG_MEM_SIZE_PER_THREAD * ps_prms->i4_num_proc_thrds * i4_num_me_frm_pllel;
if(mem_avail)
{
U08 *pu1_mem = ps_memtabs[count].pu1_mem;
ASSERT(ps_memtabs[count].size == size);
for(num_thrds = 0; num_thrds < ps_prms->i4_num_proc_thrds; num_thrds++)
{
me_frm_ctxt_t *ps_frm_ctxt;
ps_ctxt = ps_master_ctxt->aps_me_ctxt[num_thrds];
for(i = 0; i < MAX_NUM_ME_PARALLEL; i++)
{
ps_frm_ctxt = ps_ctxt->aps_me_frm_prms[i];
hme_init_wkg_mem(&ps_frm_ctxt->s_buf_mgr, pu1_mem, MAX_WKG_MEM_SIZE_PER_THREAD);
if(i4_num_me_frm_pllel != 1)
{
/* update the memory buffer pointer */
pu1_mem += MAX_WKG_MEM_SIZE_PER_THREAD;
}
}
if(i4_num_me_frm_pllel == 1)
{
pu1_mem += MAX_WKG_MEM_SIZE_PER_THREAD;
}
}
}
else
{
ps_memtabs[count].size = size;
ps_memtabs[count].align = 4;
ps_memtabs[count].e_mem_attr = HME_SCRATCH_OVLY_MEM;
}
count++;
/*************************************************************************/
/* Memtab : We need 64x64 buffer to store the entire CTB input for bidir */
/* refinement. This memtab stores 2I - P0, I is input and P0 is L0 pred */
/*************************************************************************/
size = sizeof(S16) * CTB_BLK_SIZE * CTB_BLK_SIZE * ps_prms->i4_num_proc_thrds *
i4_num_me_frm_pllel;
if(mem_avail)
{
S16 *pi2_mem = (S16 *)ps_memtabs[count].pu1_mem;
ASSERT(ps_memtabs[count].size == size);
for(num_thrds = 0; num_thrds < ps_prms->i4_num_proc_thrds; num_thrds++)
{
me_frm_ctxt_t *ps_frm_ctxt;
ps_ctxt = ps_master_ctxt->aps_me_ctxt[num_thrds];
for(i = 0; i < MAX_NUM_ME_PARALLEL; i++)
{
ps_frm_ctxt = ps_ctxt->aps_me_frm_prms[i];
ps_frm_ctxt->pi2_inp_bck = pi2_mem;
/** If no me frames running in parallel update the other aps_me_frm_prms indices with same memory **/
if(i4_num_me_frm_pllel != 1)
{
pi2_mem += (CTB_BLK_SIZE * CTB_BLK_SIZE);
}
}
if(i4_num_me_frm_pllel == 1)
{
pi2_mem += (CTB_BLK_SIZE * CTB_BLK_SIZE);
}
}
}
else
{
ps_memtabs[count].size = size;
ps_memtabs[count].align = 16;
ps_memtabs[count].e_mem_attr = HME_SCRATCH_OVLY_MEM;
}
count++;
/* Allocate a memtab for each histogram. As many as num ref and number of threads */
/* Loop across for each ME_FRM in PARALLEL */
for(j = 0; j < MAX_NUM_ME_PARALLEL; j++)
{
for(i = 0; i < ps_prms->max_num_ref; i++)
{
size = ps_prms->i4_num_proc_thrds * sizeof(mv_hist_t);
if(mem_avail)
{
mv_hist_t *ps_mv_hist = (mv_hist_t *)ps_memtabs[count].pu1_mem;
ASSERT(size == ps_memtabs[count].size);
/* divide the memory accross the threads */
for(num_thrds = 0; num_thrds < ps_prms->i4_num_proc_thrds; num_thrds++)
{
ps_ctxt = ps_master_ctxt->aps_me_ctxt[num_thrds];
ps_ctxt->aps_me_frm_prms[j]->aps_mv_hist[i] = ps_mv_hist;
ps_mv_hist++;
}
}
else
{
ps_memtabs[count].size = size;
ps_memtabs[count].align = 8;
ps_memtabs[count].e_mem_attr = HME_PERSISTENT_MEM;
}
count++;
}
if((i4_num_me_frm_pllel == 1) && (j != (MAX_NUM_ME_PARALLEL - 1)))
{
/** If no me frames running in parallel update the other aps_me_frm_prms indices with same memory **/
/** bring the count back to earlier value if there are no me frames in parallel. don't decrement for last loop **/
count -= ps_prms->max_num_ref;
}
}
/* Memtabs : Search nodes for 16x16 CUs, 32x32 and 64x64 CUs */
for(j = 0; j < MAX_NUM_ME_PARALLEL; j++)
{
S32 count_cpy = count;
for(num_thrds = 0; num_thrds < ps_prms->i4_num_proc_thrds; num_thrds++)
{
if(mem_avail)
{
ps_ctxt = ps_master_ctxt->aps_me_ctxt[num_thrds];
}
for(i = 0; i < 21; i++)
{
search_results_t *ps_search_results = NULL;
if(mem_avail)
{
if(i < 16)
{
ps_search_results =
&ps_ctxt->aps_me_frm_prms[j]->as_search_results_16x16[i];
}
else if(i < 20)
{
ps_search_results =
&ps_ctxt->aps_me_frm_prms[j]->as_search_results_32x32[i - 16];
ps_search_results->ps_cu_results =
&ps_ctxt->aps_me_frm_prms[j]->as_cu32x32_results[i - 16];
}
else if(i == 20)
{
ps_search_results = &ps_ctxt->aps_me_frm_prms[j]->s_search_results_64x64;
ps_search_results->ps_cu_results =
&ps_ctxt->aps_me_frm_prms[j]->s_cu64x64_results;
}
else
{
/* 8x8 search results are not required in LO ME */
ASSERT(0);
}
}
count += hme_alloc_init_search_nodes(
ps_search_results, &ps_memtabs[count], mem_avail, 2, ps_prms->max_num_results);
}
}
if((i4_num_me_frm_pllel == 1) && (j != (MAX_NUM_ME_PARALLEL - 1)))
{
count = count_cpy;
}
}
/* Weighted inputs, one for each ref + one non weighted */
for(j = 0; j < MAX_NUM_ME_PARALLEL; j++)
{
size = (ps_prms->max_num_ref + 1) * ctb_wd * ctb_wd * ps_prms->i4_num_proc_thrds;
if(mem_avail)
{
U08 *pu1_mem;
ASSERT(ps_memtabs[count].size == size);
pu1_mem = ps_memtabs[count].pu1_mem;
for(num_thrds = 0; num_thrds < ps_prms->i4_num_proc_thrds; num_thrds++)
{
ps_ctxt = ps_master_ctxt->aps_me_ctxt[num_thrds];
for(i = 0; i < ps_prms->max_num_ref + 1; i++)
{
ps_ctxt->aps_me_frm_prms[j]->s_wt_pred.apu1_wt_inp_buf_array[i] = pu1_mem;
pu1_mem += (ctb_wd * ctb_wd);
}
}
}
else
{
ps_memtabs[count].size = size;
ps_memtabs[count].align = 16;
ps_memtabs[count].e_mem_attr = HME_SCRATCH_OVLY_MEM;
}
if((i4_num_me_frm_pllel != 1) || (j == (MAX_NUM_ME_PARALLEL - 1)))
{
count++;
}
}
/* if memory is allocated the intislaise the frm prms ptr to each thrd */
if(mem_avail)
{
for(num_thrds = 0; num_thrds < ps_prms->i4_num_proc_thrds; num_thrds++)
{
me_frm_ctxt_t *ps_frm_ctxt;
ps_ctxt = ps_master_ctxt->aps_me_ctxt[num_thrds];
for(i = 0; i < MAX_NUM_ME_PARALLEL; i++)
{
ps_frm_ctxt = ps_ctxt->aps_me_frm_prms[i];
ps_frm_ctxt->ps_hme_frm_prms = &ps_master_ctxt->as_frm_prms[i];
ps_frm_ctxt->ps_hme_ref_map = &ps_master_ctxt->as_ref_map[i];
}
}
}
/* Memory allocation for use in Clustering */
if(ps_prms->s_me_coding_tools.e_me_quality_presets == ME_PRISTINE_QUALITY)
{
for(i = 0; i < MAX_NUM_ME_PARALLEL; i++)
{
size = 16 * sizeof(cluster_16x16_blk_t) + 4 * sizeof(cluster_32x32_blk_t) +
sizeof(cluster_64x64_blk_t) + sizeof(ctb_cluster_info_t);
size *= ps_prms->i4_num_proc_thrds;
if(mem_avail)
{
U08 *pu1_mem;
ASSERT(ps_memtabs[count].size == size);
pu1_mem = ps_memtabs[count].pu1_mem;
for(num_thrds = 0; num_thrds < ps_prms->i4_num_proc_thrds; num_thrds++)
{
ps_ctxt = ps_master_ctxt->aps_me_ctxt[num_thrds];
ps_ctxt->aps_me_frm_prms[i]->ps_blk_16x16 = (cluster_16x16_blk_t *)pu1_mem;
pu1_mem += (16 * sizeof(cluster_16x16_blk_t));
ps_ctxt->aps_me_frm_prms[i]->ps_blk_32x32 = (cluster_32x32_blk_t *)pu1_mem;
pu1_mem += (4 * sizeof(cluster_32x32_blk_t));
ps_ctxt->aps_me_frm_prms[i]->ps_blk_64x64 = (cluster_64x64_blk_t *)pu1_mem;
pu1_mem += (sizeof(cluster_64x64_blk_t));
ps_ctxt->aps_me_frm_prms[i]->ps_ctb_cluster_info =
(ctb_cluster_info_t *)pu1_mem;
pu1_mem += (sizeof(ctb_cluster_info_t));
}
}
else
{
ps_memtabs[count].size = size;
ps_memtabs[count].align = 16;
ps_memtabs[count].e_mem_attr = HME_SCRATCH_OVLY_MEM;
}
if((i4_num_me_frm_pllel != 1) || (i == (MAX_NUM_ME_PARALLEL - 1)))
{
count++;
}
}
}
else if(mem_avail)
{
for(i = 0; i < MAX_NUM_ME_PARALLEL; i++)
{
for(num_thrds = 0; num_thrds < ps_prms->i4_num_proc_thrds; num_thrds++)
{
ps_ctxt = ps_master_ctxt->aps_me_ctxt[num_thrds];
ps_ctxt->aps_me_frm_prms[i]->ps_blk_16x16 = NULL;
ps_ctxt->aps_me_frm_prms[i]->ps_blk_32x32 = NULL;
ps_ctxt->aps_me_frm_prms[i]->ps_blk_64x64 = NULL;
ps_ctxt->aps_me_frm_prms[i]->ps_ctb_cluster_info = NULL;
}
}
}
for(i = 0; i < MAX_NUM_ME_PARALLEL; i++)
{
size = sizeof(fullpel_refine_ctxt_t);
size *= ps_prms->i4_num_proc_thrds;
if(mem_avail)
{
U08 *pu1_mem;
ASSERT(ps_memtabs[count].size == size);
pu1_mem = ps_memtabs[count].pu1_mem;
for(num_thrds = 0; num_thrds < ps_prms->i4_num_proc_thrds; num_thrds++)
{
ps_ctxt = ps_master_ctxt->aps_me_ctxt[num_thrds];
ps_ctxt->aps_me_frm_prms[i]->ps_fullpel_refine_ctxt =
(fullpel_refine_ctxt_t *)pu1_mem;
pu1_mem += (sizeof(fullpel_refine_ctxt_t));
}
}
else
{
ps_memtabs[count].size = size;
ps_memtabs[count].align = 16;
ps_memtabs[count].e_mem_attr = HME_SCRATCH_OVLY_MEM;
}
if((i4_num_me_frm_pllel != 1) || (i == (MAX_NUM_ME_PARALLEL - 1)))
{
count++;
}
}
/* Memory for ihevce_me_optimised_function_list_t struct */
if(mem_avail)
{
ps_master_ctxt->pv_me_optimised_function_list = (void *)ps_memtabs[count++].pu1_mem;
}
else
{
ps_memtabs[count].size = sizeof(ihevce_me_optimised_function_list_t);
ps_memtabs[count].align = 16;
ps_memtabs[count++].e_mem_attr = HME_SCRATCH_OVLY_MEM;
}
ASSERT(count < hme_enc_num_alloc(i4_num_me_frm_pllel));
return (count);
}
/**
********************************************************************************
* @fn hme_coarse_alloc_init_mem()
*
* @brief Requests/ assign memory based on mem avail
*
* @param[in] ps_memtabs : memtab array
*
* @param[in] ps_prms : init prms
*
* @param[in] pv_ctxt : ME ctxt
*
* @param[in] mem_avail : request/assign flag
*
* @return number of memtabs
********************************************************************************
*/
S32 hme_coarse_alloc_init_mem(
hme_memtab_t *ps_memtabs, hme_init_prms_t *ps_prms, void *pv_ctxt, S32 mem_avail)
{
coarse_me_master_ctxt_t *ps_master_ctxt = (coarse_me_master_ctxt_t *)pv_ctxt;
coarse_me_ctxt_t *ps_ctxt;
S32 count = 0, size, i, j, use_4x4, wd;
S32 n_tot_layers;
S32 num_layers_explicit_search;
S32 a_wd[MAX_NUM_LAYERS], a_ht[MAX_NUM_LAYERS];
S32 a_disp_wd[MAX_NUM_LAYERS], a_disp_ht[MAX_NUM_LAYERS];
S32 num_results;
S32 num_thrds;
//S32 ctb_wd = 1 << ps_prms->log_ctb_size;
S32 sad_4x4_block_size, sad_4x4_block_stride, search_step, num_rows;
S32 layer1_blk_width = 8; // 8x8 search
S32 blk_shift;
/* MV bank changes */
hme_mv_t *aps_mv_bank[MAX_NUM_LAYERS] = { NULL };
S32 ai4_num_mvs_per_row[MAX_NUM_LAYERS] = { 0 };
S08 *api1_ref_idx[MAX_NUM_LAYERS] = { NULL };
/* Memtab 0: handle */
size = sizeof(coarse_me_master_ctxt_t);
if(mem_avail)
{
/* store the number of processing threads */
ps_master_ctxt->i4_num_proc_thrds = ps_prms->i4_num_proc_thrds;
}
else
{
ps_memtabs[count].size = size;
ps_memtabs[count].align = 8;
ps_memtabs[count].e_mem_attr = HME_PERSISTENT_MEM;
}
count++;
/* Memtab 1: ME threads ctxt */
size = ps_prms->i4_num_proc_thrds * sizeof(coarse_me_ctxt_t);
if(mem_avail)
{
coarse_me_ctxt_t *ps_me_tmp_ctxt = (coarse_me_ctxt_t *)ps_memtabs[count].pu1_mem;
/* store the indivisual thread ctxt pointers */
for(num_thrds = 0; num_thrds < ps_prms->i4_num_proc_thrds; num_thrds++)
{
ps_master_ctxt->aps_me_ctxt[num_thrds] = ps_me_tmp_ctxt++;
}
}
else
{
ps_memtabs[count].size = size;
ps_memtabs[count].align = 8;
ps_memtabs[count].e_mem_attr = HME_PERSISTENT_MEM;
}
count++;
memcpy(a_wd, ps_prms->a_wd, sizeof(S32) * ps_prms->num_simulcast_layers);
memcpy(a_ht, ps_prms->a_ht, sizeof(S32) * ps_prms->num_simulcast_layers);
/*************************************************************************/
/* Derive the number of HME layers, including both encoded and non encode*/
/* This function also derives the width and ht of each layer. */
/*************************************************************************/
n_tot_layers = hme_derive_num_layers(1, a_wd, a_ht, a_disp_wd, a_disp_ht);
num_layers_explicit_search = ps_prms->num_layers_explicit_search;
if(num_layers_explicit_search <= 0)
num_layers_explicit_search = n_tot_layers - 1;
num_layers_explicit_search = MIN(num_layers_explicit_search, n_tot_layers - 1);
if(mem_avail)
{
for(num_thrds = 0; num_thrds < ps_prms->i4_num_proc_thrds; num_thrds++)
{
ps_ctxt = ps_master_ctxt->aps_me_ctxt[num_thrds];
memset(ps_ctxt->u1_encode, 0, n_tot_layers);
/* encode layer should be excluded during processing */
ps_ctxt->num_layers = n_tot_layers;
memcpy(ps_ctxt->a_wd, a_wd, sizeof(S32) * n_tot_layers);
memcpy(ps_ctxt->a_ht, a_ht, sizeof(S32) * n_tot_layers);
ps_ctxt->num_layers_explicit_search = num_layers_explicit_search;
ps_ctxt->max_num_results = ps_prms->max_num_results;
ps_ctxt->max_num_results_coarse = ps_prms->max_num_results_coarse;
ps_ctxt->max_num_ref = ps_prms->max_num_ref;
}
}
/* Memtabs : Layers MV bank for total layers - 2 */
/* for penultimate layer MV bank will be initialsed at every frame level */
for(j = 1; j < n_tot_layers; j++)
{
S32 is_explicit_store = 1;
S32 wd, ht;
U08 u1_enc = 0;
wd = a_wd[j];
ht = a_ht[j];
/* Possibly implicit search for lower (finer) layers */
if(n_tot_layers - j > num_layers_explicit_search)
is_explicit_store = 0;
/* Even if explicit search, we store only 2 results (L0 and L1) */
/* in finest layer */
if(j == 0)
{
is_explicit_store = 0;
}
/* coarsest layer alwasy uses 4x4 blks to store results */
if(j == n_tot_layers - 1)
{
num_results = ps_prms->max_num_results_coarse;
}
else
{
num_results = ps_prms->max_num_results;
if(j == 0)
num_results = 1;
}
use_4x4 = hme_get_mv_blk_size(ps_prms->use_4x4, j, n_tot_layers, u1_enc);
/* for penultimate compute the parameters and store */
if(j == 1)
{
S32 num_blks, num_mvs_per_blk, num_ref;
S32 num_cols, num_rows, num_mvs_per_row;
num_cols = use_4x4 ? ((wd >> 2) + 2) : ((wd >> 3) + 2);
num_rows = use_4x4 ? ((ht >> 2) + 2) : ((ht >> 3) + 2);
if(is_explicit_store)
num_ref = ps_prms->max_num_ref;
else
num_ref = 2;
num_blks = num_cols * num_rows;
num_mvs_per_blk = num_ref * num_results;
num_mvs_per_row = num_mvs_per_blk * num_cols;
ai4_num_mvs_per_row[j] = num_mvs_per_row;
aps_mv_bank[j] = NULL;
api1_ref_idx[j] = NULL;
}
else
{
count += hme_alloc_init_layer_mv_bank(
&ps_memtabs[count],
num_results,
ps_prms->max_num_ref,
use_4x4,
mem_avail,
u1_enc,
wd,
ht,
is_explicit_store,
&aps_mv_bank[j],
&api1_ref_idx[j],
&ai4_num_mvs_per_row[j]);
}
}
/* Memtabs : Layers * num-ref + 1 */
for(i = 0; i < ps_prms->max_num_ref + 1 + NUM_BUFS_DECOMP_HME; i++)
{
/* for all layer except encode layer */
for(j = 1; j < n_tot_layers; j++)
{
layer_ctxt_t *ps_layer;
S32 is_explicit_store = 1;
S32 segment_this_layer = (j == 0) ? 1 : ps_prms->segment_higher_layers;
S32 wd, ht;
U08 u1_enc = 0;
wd = a_wd[j];
ht = a_ht[j];
/* Possibly implicit search for lower (finer) layers */
if(n_tot_layers - j > num_layers_explicit_search)
is_explicit_store = 0;
/* Even if explicit search, we store only 2 results (L0 and L1) */
/* in finest layer */
if(j == 0)
{
is_explicit_store = 0;
}
/* coarsest layer alwasy uses 4x4 blks to store results */
if(j == n_tot_layers - 1)
{
num_results = ps_prms->max_num_results_coarse;
}
else
{
num_results = ps_prms->max_num_results;
if(j == 0)
num_results = 1;
}
use_4x4 = hme_get_mv_blk_size(ps_prms->use_4x4, j, n_tot_layers, u1_enc);
count += hme_alloc_init_layer(
&ps_memtabs[count],
num_results,
ps_prms->max_num_ref,
use_4x4,
mem_avail,
u1_enc,
wd,
ht,
a_disp_wd[j],
a_disp_ht[j],
segment_this_layer,
is_explicit_store,
&ps_layer);
if(mem_avail)
{
/* same ps_layer memory pointer is stored in all the threads */
for(num_thrds = 0; num_thrds < ps_prms->i4_num_proc_thrds; num_thrds++)
{
ps_ctxt = ps_master_ctxt->aps_me_ctxt[num_thrds];
ps_ctxt->as_ref_descr[i].aps_layers[j] = ps_layer;
}
/* store the MV bank pointers */
ps_layer->ps_layer_mvbank->max_num_mvs_per_row = ai4_num_mvs_per_row[j];
ps_layer->ps_layer_mvbank->ps_mv_base = aps_mv_bank[j];
ps_layer->ps_layer_mvbank->pi1_ref_idx_base = api1_ref_idx[j];
}
}
}
/* Memtabs : Prev Row search node at coarsest layer */
wd = a_wd[n_tot_layers - 1];
/* Allocate a memtab for storing 4x4 SADs for n rows. As many as num ref and number of threads */
num_rows = ps_prms->i4_num_proc_thrds + 1;
if(ps_prms->s_me_coding_tools.e_me_quality_presets < ME_MEDIUM_SPEED)
search_step = HME_COARSE_STEP_SIZE_HIGH_QUALITY;
else
search_step = HME_COARSE_STEP_SIZE_HIGH_SPEED;
/*shift factor*/
blk_shift = 2; /*4x4*/
search_step >>= 1;
sad_4x4_block_size = ((2 * MAX_MVX_SUPPORTED_IN_COARSE_LAYER) >> search_step) *
((2 * MAX_MVY_SUPPORTED_IN_COARSE_LAYER) >> search_step);
sad_4x4_block_stride = ((wd >> blk_shift) + 1) * sad_4x4_block_size;
size = num_rows * sad_4x4_block_stride * sizeof(S16);
for(i = 0; i < ps_prms->max_num_ref; i++)
{
if(mem_avail)
{
ASSERT(size == ps_memtabs[count].size);
/* same row memory pointer is stored in all the threads */
for(num_thrds = 0; num_thrds < ps_prms->i4_num_proc_thrds; num_thrds++)
{
ps_ctxt = ps_master_ctxt->aps_me_ctxt[num_thrds];
ps_ctxt->api2_sads_4x4_n_rows[i] = (S16 *)ps_memtabs[count].pu1_mem;
}
}
else
{
ps_memtabs[count].size = size;
ps_memtabs[count].align = 4;
ps_memtabs[count].e_mem_attr = HME_SCRATCH_OVLY_MEM;
}
count++;
}
/* Allocate a memtab for storing best search nodes 8x4 for n rows. Row is allocated for worst case (2*min_wd_coarse/4). As many as num ref and number of threads */
size = num_rows * ((wd >> blk_shift) + 1) * sizeof(search_node_t);
for(i = 0; i < ps_prms->max_num_ref; i++)
{
if(mem_avail)
{
ASSERT(size == ps_memtabs[count].size);
/* same row memory pointer is stored in all the threads */
for(num_thrds = 0; num_thrds < ps_prms->i4_num_proc_thrds; num_thrds++)
{
ps_ctxt = ps_master_ctxt->aps_me_ctxt[num_thrds];
ps_ctxt->aps_best_search_nodes_8x4_n_rows[i] =
(search_node_t *)ps_memtabs[count].pu1_mem;
}
}
else
{
ps_memtabs[count].size = size;
ps_memtabs[count].align = 4;
ps_memtabs[count].e_mem_attr = HME_SCRATCH_OVLY_MEM;
}
count++;
}
/* Allocate a memtab for storing best search nodes 4x8 for n rows. Row is allocated for worst case (2*min_wd_coarse/4). As many as num ref and number of threads */
size = num_rows * ((wd >> blk_shift) + 1) * sizeof(search_node_t);
for(i = 0; i < ps_prms->max_num_ref; i++)
{
if(mem_avail)
{
ASSERT(size == ps_memtabs[count].size);
/* same row memory pointer is stored in all the threads */
for(num_thrds = 0; num_thrds < ps_prms->i4_num_proc_thrds; num_thrds++)
{
ps_ctxt = ps_master_ctxt->aps_me_ctxt[num_thrds];
ps_ctxt->aps_best_search_nodes_4x8_n_rows[i] =
(search_node_t *)ps_memtabs[count].pu1_mem;
}
}
else
{
ps_memtabs[count].size = size;
ps_memtabs[count].align = 4;
ps_memtabs[count].e_mem_attr = HME_SCRATCH_OVLY_MEM;
}
count++;
}
/* Allocate a memtab for each histogram. As many as num ref and number of threads */
for(i = 0; i < ps_prms->max_num_ref; i++)
{
size = ps_prms->i4_num_proc_thrds * sizeof(mv_hist_t);
if(mem_avail)
{
mv_hist_t *ps_mv_hist = (mv_hist_t *)ps_memtabs[count].pu1_mem;
ASSERT(size == ps_memtabs[count].size);
/* divide the memory accross the threads */
for(num_thrds = 0; num_thrds < ps_prms->i4_num_proc_thrds; num_thrds++)
{
ps_ctxt = ps_master_ctxt->aps_me_ctxt[num_thrds];
ps_ctxt->aps_mv_hist[i] = ps_mv_hist;
ps_mv_hist++;
}
}
else
{
ps_memtabs[count].size = size;
ps_memtabs[count].align = 8;
ps_memtabs[count].e_mem_attr = HME_PERSISTENT_MEM;
}
count++;
}
/* Memtabs : Search nodes for 8x8 blks */
for(num_thrds = 0; num_thrds < ps_prms->i4_num_proc_thrds; num_thrds++)
{
search_results_t *ps_search_results = NULL;
if(mem_avail)
{
ps_ctxt = ps_master_ctxt->aps_me_ctxt[num_thrds];
}
if(mem_avail)
{
ps_search_results = &ps_ctxt->s_search_results_8x8;
}
count += hme_alloc_init_search_nodes(
ps_search_results,
&ps_memtabs[count],
mem_avail,
ps_prms->max_num_ref,
ps_prms->max_num_results);
}
/* Weighted inputs, one for each ref */
size = (ps_prms->max_num_ref + 1) * layer1_blk_width * layer1_blk_width *
ps_prms->i4_num_proc_thrds;
if(mem_avail)
{
U08 *pu1_mem;
ASSERT(ps_memtabs[count].size == size);
pu1_mem = ps_memtabs[count].pu1_mem;
for(num_thrds = 0; num_thrds < ps_prms->i4_num_proc_thrds; num_thrds++)
{
ps_ctxt = ps_master_ctxt->aps_me_ctxt[num_thrds];
for(i = 0; i < ps_prms->max_num_ref + 1; i++)
{
ps_ctxt->s_wt_pred.apu1_wt_inp_buf_array[i] = pu1_mem;
pu1_mem += (layer1_blk_width * layer1_blk_width);
}
}
}
else
{
ps_memtabs[count].size = size;
ps_memtabs[count].align = 16;
ps_memtabs[count].e_mem_attr = HME_SCRATCH_OVLY_MEM;
}
count++;
/* if memory is allocated the intislaise the frm prms ptr to each thrd */
if(mem_avail)
{
for(num_thrds = 0; num_thrds < ps_prms->i4_num_proc_thrds; num_thrds++)
{
ps_ctxt = ps_master_ctxt->aps_me_ctxt[num_thrds];
ps_ctxt->ps_hme_frm_prms = &ps_master_ctxt->s_frm_prms;
ps_ctxt->ps_hme_ref_map = &ps_master_ctxt->s_ref_map;
}
}
/* Memory for ihevce_me_optimised_function_list_t struct */
if(mem_avail)
{
ps_master_ctxt->pv_me_optimised_function_list = (void *)ps_memtabs[count++].pu1_mem;
}
else
{
ps_memtabs[count].size = sizeof(ihevce_me_optimised_function_list_t);
ps_memtabs[count].align = 16;
ps_memtabs[count++].e_mem_attr = HME_SCRATCH_OVLY_MEM;
}
//ASSERT(count < hme_enc_num_alloc());
ASSERT(count < hme_coarse_num_alloc());
return (count);
}
/*!
******************************************************************************
* \if Function name : ihevce_coarse_me_get_lyr_prms_dep_mngr \endif
*
* \brief Returns to the caller key attributes relevant for dependency manager,
* ie, the number of vertical units in each layer
*
* \par Description:
* This function requires the precondition that the width and ht of encode
* layer is known.
* The number of layers, number of vertical units in each layer, and for
* each vertial unit in each layer, its dependency on previous layer's units
* From ME's perspective, a vertical unit is one which is smallest min size
* vertically (and spans the entire row horizontally). This is CTB for encode
* layer, and 8x8 / 4x4 for non encode layers.
*
* \param[in] num_layers : Number of ME Layers
* \param[in] pai4_ht : Array storing ht at each layer
* \param[in] pai4_wd : Array storing wd at each layer
* \param[out] pi4_num_vert_units_in_lyr : Array of size N (num layers), each
* entry has num vertical units in that particular layer
*
* \return
* None
*
* \author
* Ittiam
*
*****************************************************************************
*/
void ihevce_coarse_me_get_lyr_prms_dep_mngr(
WORD32 num_layers, WORD32 *pai4_ht, WORD32 *pai4_wd, WORD32 *pai4_num_vert_units_in_lyr)
{
/* Height of current and next layers */
WORD32 ht_c, ht_n;
/* Blk ht at a given layer and next layer*/
WORD32 unit_ht_c, unit_ht_n, blk_ht_c, blk_ht_n;
/* Number of vertical units in current and next layer */
WORD32 num_vert_c, num_vert_n;
WORD32 ctb_size = 64, num_enc_layers = 1, use_4x4 = 1, i;
UWORD8 au1_encode[MAX_NUM_LAYERS];
memset(au1_encode, 0, num_layers);
memset(au1_encode, 1, num_enc_layers);
ht_n = pai4_ht[num_layers - 2];
ht_c = pai4_ht[num_layers - 1];
/* compute blk ht and unit ht for c and n */
if(au1_encode[num_layers - 1])
{
blk_ht_c = 16;
unit_ht_c = ctb_size;
}
else
{
blk_ht_c = hme_get_blk_size(use_4x4, num_layers - 1, num_layers, 0);
unit_ht_c = blk_ht_c;
}
num_vert_c = (ht_c + unit_ht_c - 1) / unit_ht_c;
/* For new design in Coarsest HME layer we need */
/* one additional row extra at the end of frame */
/* hence num_vert_c is incremented by 1 */
num_vert_c++;
/*************************************************************************/
/* Run through each layer, set the number of vertical units */
/*************************************************************************/
for(i = num_layers - 1; i > 0; i--)
{
pai4_num_vert_units_in_lyr[i] = num_vert_c;
/* "n" is computed for first time */
ht_n = pai4_ht[i - 1];
blk_ht_n = hme_get_blk_size(use_4x4, i - 1, num_layers, 0);
unit_ht_n = blk_ht_n;
if(au1_encode[i - 1])
unit_ht_n = ctb_size;
num_vert_n = (ht_n + unit_ht_n - 1) / unit_ht_n;
/* Compute the blk size and vert unit size in each layer */
/* "c" denotes curr layer, and "n" denotes the layer to which result */
/* is projected to */
ht_c = ht_n;
blk_ht_c = blk_ht_n;
unit_ht_c = unit_ht_n;
num_vert_c = num_vert_n;
}
/* LAYER 0 OR ENCODE LAYER UPDATE : NO OUTPUT DEPS */
/* set the numebr of vertical units */
pai4_num_vert_units_in_lyr[0] = num_vert_c;
}
/**
********************************************************************************
* @fn hme_coarse_dep_mngr_alloc_mem()
*
* @brief Requests memory for HME Dep Mngr
*
* \param[in,out] ps_mem_tab : pointer to memory descriptors table
* \param[in] ps_init_prms : Create time static parameters
* \param[in] i4_mem_space : memspace in whihc memory request should be done
*
* @return number of memtabs
********************************************************************************
*/
WORD32 hme_coarse_dep_mngr_alloc_mem(
iv_mem_rec_t *ps_mem_tab,
ihevce_static_cfg_params_t *ps_init_prms,
WORD32 i4_mem_space,
WORD32 i4_num_proc_thrds,
WORD32 i4_resolution_id)
{
WORD32 ai4_num_vert_units_in_lyr[MAX_NUM_HME_LAYERS];
WORD32 a_wd[MAX_NUM_HME_LAYERS], a_ht[MAX_NUM_HME_LAYERS];
WORD32 a_disp_wd[MAX_NUM_HME_LAYERS], a_disp_ht[MAX_NUM_HME_LAYERS];
WORD32 n_enc_layers = 1, n_tot_layers, n_dep_tabs = 0, i;
WORD32 min_cu_size;
/* get the min cu size from config params */
min_cu_size = ps_init_prms->s_config_prms.i4_min_log2_cu_size;
min_cu_size = 1 << min_cu_size;
/* Get the width and heights of different decomp layers */
*a_wd = ps_init_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_width +
SET_CTB_ALIGN(
ps_init_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_width, min_cu_size);
*a_ht =
ps_init_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_height +
SET_CTB_ALIGN(
ps_init_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_height, min_cu_size);
n_tot_layers = hme_derive_num_layers(n_enc_layers, a_wd, a_ht, a_disp_wd, a_disp_ht);
ASSERT(n_tot_layers >= 3);
/* --- Get the number of vartical units in each layer for dep. mngr -- */
ihevce_coarse_me_get_lyr_prms_dep_mngr(
n_tot_layers, &a_ht[0], &a_wd[0], &ai4_num_vert_units_in_lyr[0]);
/* Fill memtabs for HME layers,except for L0 layer */
for(i = 1; i < n_tot_layers; i++)
{
n_dep_tabs += ihevce_dmgr_get_mem_recs(
&ps_mem_tab[n_dep_tabs],
DEP_MNGR_ROW_ROW_SYNC,
ai4_num_vert_units_in_lyr[i],
1, /* Number of Col Tiles : Not supported in PreEnc */
i4_num_proc_thrds,
i4_mem_space);
}
ASSERT(n_dep_tabs <= hme_coarse_dep_mngr_num_alloc());
return (n_dep_tabs);
}
/**
********************************************************************************
* @fn hme_coarse_dep_mngr_init()
*
* @brief Assign memory for HME Dep Mngr
*
* \param[in,out] ps_mem_tab : pointer to memory descriptors table
* \param[in] ps_init_prms : Create time static parameters
* @param[in] pv_ctxt : ME ctxt
* \param[in] pv_osal_handle : Osal handle
*
* @return number of memtabs
********************************************************************************
*/
WORD32 hme_coarse_dep_mngr_init(
iv_mem_rec_t *ps_mem_tab,
ihevce_static_cfg_params_t *ps_init_prms,
void *pv_ctxt,
void *pv_osal_handle,
WORD32 i4_num_proc_thrds,
WORD32 i4_resolution_id)
{
WORD32 ai4_num_vert_units_in_lyr[MAX_NUM_HME_LAYERS];
WORD32 a_wd[MAX_NUM_HME_LAYERS], a_ht[MAX_NUM_HME_LAYERS];
WORD32 a_disp_wd[MAX_NUM_HME_LAYERS], a_disp_ht[MAX_NUM_HME_LAYERS];
WORD32 n_enc_layers = 1, n_tot_layers, n_dep_tabs = 0, i;
WORD32 min_cu_size;
coarse_me_master_ctxt_t *ps_me_ctxt = (coarse_me_master_ctxt_t *)pv_ctxt;
/* get the min cu size from config params */
min_cu_size = ps_init_prms->s_config_prms.i4_min_log2_cu_size;
min_cu_size = 1 << min_cu_size;
/* Get the width and heights of different decomp layers */
*a_wd = ps_init_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_width +
SET_CTB_ALIGN(
ps_init_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_width, min_cu_size);
*a_ht =
ps_init_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_height +
SET_CTB_ALIGN(
ps_init_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_height, min_cu_size);
n_tot_layers = hme_derive_num_layers(n_enc_layers, a_wd, a_ht, a_disp_wd, a_disp_ht);
ASSERT(n_tot_layers >= 3);
/* --- Get the number of vartical units in each layer for dep. mngr -- */
ihevce_coarse_me_get_lyr_prms_dep_mngr(
n_tot_layers, &a_ht[0], &a_wd[0], &ai4_num_vert_units_in_lyr[0]);
/* --- HME sync Dep Mngr Mem init -- */
for(i = 1; i < n_tot_layers; i++)
{
WORD32 num_blks_in_row, num_blks_in_pic, blk_size_shift;
if(i == (n_tot_layers - 1)) /* coarsest layer */
blk_size_shift = 2;
else
blk_size_shift = 3; /* refine layers */
GET_NUM_BLKS_IN_PIC(a_wd[i], a_ht[i], blk_size_shift, num_blks_in_row, num_blks_in_pic);
/* Coarsest layer : 1 block extra, since the last block */
if(i == (n_tot_layers - 1)) /* in a row needs East block */
num_blks_in_row += 1;
/* Note : i-1, only for HME layers, L0 is separate */
ps_me_ctxt->apv_dep_mngr_hme_sync[i - 1] = ihevce_dmgr_init(
&ps_mem_tab[n_dep_tabs],
pv_osal_handle,
DEP_MNGR_ROW_ROW_SYNC,
ai4_num_vert_units_in_lyr[i],
num_blks_in_row,
1, /* Number of Col Tiles : Not supported in PreEnc */
i4_num_proc_thrds,
1 /*Sem disabled*/
);
n_dep_tabs += ihevce_dmgr_get_num_mem_recs();
}
return n_dep_tabs;
}
/**
********************************************************************************
* @fn hme_coarse_dep_mngr_reg_sem()
*
* @brief Assign semaphores for HME Dep Mngr
*
* \param[in] pv_me_ctxt : pointer to Coarse ME ctxt
* \param[in] ppv_sem_hdls : Arry of semaphore handles
* \param[in] i4_num_proc_thrds : Number of processing threads
*
* @return number of memtabs
********************************************************************************
*/
void hme_coarse_dep_mngr_reg_sem(void *pv_ctxt, void **ppv_sem_hdls, WORD32 i4_num_proc_thrds)
{
WORD32 i;
coarse_me_master_ctxt_t *ps_me_ctxt = (coarse_me_master_ctxt_t *)pv_ctxt;
coarse_me_ctxt_t *ps_ctxt = ps_me_ctxt->aps_me_ctxt[0];
/* --- HME sync Dep Mngr semaphore init -- */
for(i = 1; i < ps_ctxt->num_layers; i++)
{
ihevce_dmgr_reg_sem_hdls(
ps_me_ctxt->apv_dep_mngr_hme_sync[i - 1], ppv_sem_hdls, i4_num_proc_thrds);
}
return;
}
/**
********************************************************************************
* @fn hme_coarse_dep_mngr_delete()
*
* Destroy Coarse ME Dep Mngr module
* Note : Only Destroys the resources allocated in the module like
* semaphore,etc. Memory free is done Separately using memtabs
*
* \param[in] pv_me_ctxt : pointer to Coarse ME ctxt
* \param[in] ps_init_prms : Create time static parameters
*
* @return none
********************************************************************************
*/
void hme_coarse_dep_mngr_delete(
void *pv_me_ctxt, ihevce_static_cfg_params_t *ps_init_prms, WORD32 i4_resolution_id)
{
WORD32 a_wd[MAX_NUM_HME_LAYERS], a_ht[MAX_NUM_HME_LAYERS];
WORD32 a_disp_wd[MAX_NUM_HME_LAYERS], a_disp_ht[MAX_NUM_HME_LAYERS];
WORD32 n_enc_layers = 1, n_tot_layers, i;
WORD32 min_cu_size;
coarse_me_master_ctxt_t *ps_me_ctxt = (coarse_me_master_ctxt_t *)pv_me_ctxt;
/* get the min cu size from config params */
min_cu_size = ps_init_prms->s_config_prms.i4_min_log2_cu_size;
min_cu_size = 1 << min_cu_size;
/* Get the width and heights of different decomp layers */
*a_wd = ps_init_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_width +
SET_CTB_ALIGN(
ps_init_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_width, min_cu_size);
*a_ht =
ps_init_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_height +
SET_CTB_ALIGN(
ps_init_prms->s_tgt_lyr_prms.as_tgt_params[i4_resolution_id].i4_height, min_cu_size);
n_tot_layers = hme_derive_num_layers(n_enc_layers, a_wd, a_ht, a_disp_wd, a_disp_ht);
ASSERT(n_tot_layers >= 3);
/* --- HME sync Dep Mngr Delete -- */
for(i = 1; i < n_tot_layers; i++)
{
/* Note : i-1, only for HME layers, L0 is separate */
ihevce_dmgr_del(ps_me_ctxt->apv_dep_mngr_hme_sync[i - 1]);
}
}
/**
*******************************************************************************
* @fn S32 hme_enc_alloc(hme_memtab_t *ps_memtabs, hme_init_prms_t *ps_prms)
*
* @brief Fills up memtabs with memory information details required by HME
*
* @param[out] ps_memtabs : Pointre to an array of memtabs where module fills
* up its requirements of memory
*
* @param[in] ps_prms : Input parameters to module crucial in calculating reqd
* amt of memory
*
* @return Number of memtabs required
*******************************************************************************
*/
S32 hme_enc_alloc(hme_memtab_t *ps_memtabs, hme_init_prms_t *ps_prms, WORD32 i4_num_me_frm_pllel)
{
S32 num, tot, i;
/* Validation of init params */
if(-1 == hme_validate_init_prms(ps_prms))
return (-1);
num = hme_enc_alloc_init_mem(ps_memtabs, ps_prms, NULL, 0, i4_num_me_frm_pllel);
tot = hme_enc_num_alloc(i4_num_me_frm_pllel);
for(i = num; i < tot; i++)
{
ps_memtabs[i].size = 4;
ps_memtabs[i].align = 4;
ps_memtabs[i].e_mem_attr = HME_PERSISTENT_MEM;
}
return (tot);
}
/**
*******************************************************************************
* @fn S32 hme_coarse_alloc(hme_memtab_t *ps_memtabs, hme_init_prms_t *ps_prms)
*
* @brief Fills up memtabs with memory information details required by Coarse HME
*
* @param[out] ps_memtabs : Pointre to an array of memtabs where module fills
* up its requirements of memory
*
* @param[in] ps_prms : Input parameters to module crucial in calculating reqd
* amt of memory
*
* @return Number of memtabs required
*******************************************************************************
*/
S32 hme_coarse_alloc(hme_memtab_t *ps_memtabs, hme_init_prms_t *ps_prms)
{
S32 num, tot, i;
/* Validation of init params */
if(-1 == hme_validate_init_prms(ps_prms))
return (-1);
num = hme_coarse_alloc_init_mem(ps_memtabs, ps_prms, NULL, 0);
tot = hme_coarse_num_alloc();
for(i = num; i < tot; i++)
{
ps_memtabs[i].size = 4;
ps_memtabs[i].align = 4;
ps_memtabs[i].e_mem_attr = HME_PERSISTENT_MEM;
}
return (tot);
}
/**
*******************************************************************************
* @fn hme_coarse_dep_mngr_alloc
*
* @brief Fills up memtabs with memory information details required by Coarse HME
*
* \param[in,out] ps_mem_tab : pointer to memory descriptors table
* \param[in] ps_init_prms : Create time static parameters
* \param[in] i4_mem_space : memspace in whihc memory request should be done
*
* @return Number of memtabs required
*******************************************************************************
*/
WORD32 hme_coarse_dep_mngr_alloc(
iv_mem_rec_t *ps_mem_tab,
ihevce_static_cfg_params_t *ps_init_prms,
WORD32 i4_mem_space,
WORD32 i4_num_proc_thrds,
WORD32 i4_resolution_id)
{
S32 num, tot, i;
num = hme_coarse_dep_mngr_alloc_mem(
ps_mem_tab, ps_init_prms, i4_mem_space, i4_num_proc_thrds, i4_resolution_id);
tot = hme_coarse_dep_mngr_num_alloc();
for(i = num; i < tot; i++)
{
ps_mem_tab[i].i4_mem_size = 4;
ps_mem_tab[i].i4_mem_alignment = 4;
ps_mem_tab[i].e_mem_type = (IV_MEM_TYPE_T)i4_mem_space;
}
return (tot);
}
/**
********************************************************************************
* @fn hme_coarse_init_ctxt()
*
* @brief initialise context memory
*
* @param[in] ps_prms : init prms
*
* @param[in] pv_ctxt : ME ctxt
*
* @return number of memtabs
********************************************************************************
*/
void hme_coarse_init_ctxt(coarse_me_master_ctxt_t *ps_master_ctxt, hme_init_prms_t *ps_prms)
{
S32 i, j, num_thrds;
coarse_me_ctxt_t *ps_ctxt;
S32 num_rows_coarse;
/* initialise the parameters inot context of all threads */
for(num_thrds = 0; num_thrds < ps_master_ctxt->i4_num_proc_thrds; num_thrds++)
{
ps_ctxt = ps_master_ctxt->aps_me_ctxt[num_thrds];
/* Copy the init prms to context */
ps_ctxt->s_init_prms = *ps_prms;
/* Initialize some other variables in ctxt */
ps_ctxt->i4_prev_poc = -1;
ps_ctxt->num_b_frms = ps_prms->num_b_frms;
ps_ctxt->apu1_ref_bits_tlu_lc[0] = &ps_ctxt->au1_ref_bits_tlu_lc[0][0];
ps_ctxt->apu1_ref_bits_tlu_lc[1] = &ps_ctxt->au1_ref_bits_tlu_lc[1][0];
/* Initialize num rows lookuptable */
ps_ctxt->i4_num_row_bufs = ps_prms->i4_num_proc_thrds + 1;
num_rows_coarse = ps_ctxt->i4_num_row_bufs;
for(i = 0; i < ((HEVCE_MAX_HEIGHT >> 1) >> 2); i++)
{
ps_ctxt->ai4_row_index[i] = (i % num_rows_coarse);
}
}
/* since same layer desc pointer is stored in all the threads ctxt */
/* layer init is done only using 0th thread ctxt */
ps_ctxt = ps_master_ctxt->aps_me_ctxt[0];
/* Initialize all layers descriptors to have -1 = poc meaning unfilled */
for(i = 0; i < ps_ctxt->max_num_ref + 1 + NUM_BUFS_DECOMP_HME; i++)
{
for(j = 1; j < ps_ctxt->num_layers; j++)
{
layer_ctxt_t *ps_layer;
ps_layer = ps_ctxt->as_ref_descr[i].aps_layers[j];
ps_layer->i4_poc = -1;
ps_layer->ppu1_list_inp = &ps_ctxt->apu1_list_inp[j][0];
memset(
ps_layer->s_global_mv, 0, sizeof(hme_mv_t) * ps_ctxt->max_num_ref * NUM_GMV_LOBES);
}
}
}
/**
********************************************************************************
* @fn hme_enc_init_ctxt()
*
* @brief initialise context memory
*
* @param[in] ps_prms : init prms
*
* @param[in] pv_ctxt : ME ctxt
*
* @return number of memtabs
********************************************************************************
*/
void hme_enc_init_ctxt(
me_master_ctxt_t *ps_master_ctxt, hme_init_prms_t *ps_prms, rc_quant_t *ps_rc_quant_ctxt)
{
S32 i, j, num_thrds;
me_ctxt_t *ps_ctxt;
me_frm_ctxt_t *ps_frm_ctxt;
/* initialise the parameters in context of all threads */
for(num_thrds = 0; num_thrds < ps_master_ctxt->i4_num_proc_thrds; num_thrds++)
{
ps_ctxt = ps_master_ctxt->aps_me_ctxt[num_thrds];
/* Store Tile params base into ME context */
ps_ctxt->pv_tile_params_base = ps_master_ctxt->pv_tile_params_base;
for(i = 0; i < MAX_NUM_ME_PARALLEL; i++)
{
ps_frm_ctxt = ps_ctxt->aps_me_frm_prms[i];
/* Copy the init prms to context */
ps_ctxt->s_init_prms = *ps_prms;
/* Initialize some other variables in ctxt */
ps_frm_ctxt->i4_prev_poc = INVALID_POC;
ps_frm_ctxt->log_ctb_size = ps_prms->log_ctb_size;
ps_frm_ctxt->num_b_frms = ps_prms->num_b_frms;
ps_frm_ctxt->i4_is_prev_frame_reference = 0;
ps_frm_ctxt->ps_rc_quant_ctxt = ps_rc_quant_ctxt;
/* Initialize mv grids for L0 and L1 used in final refinement layer */
{
hme_init_mv_grid(&ps_frm_ctxt->as_mv_grid[0]);
hme_init_mv_grid(&ps_frm_ctxt->as_mv_grid[1]);
hme_init_mv_grid(&ps_frm_ctxt->as_mv_grid_fpel[0]);
hme_init_mv_grid(&ps_frm_ctxt->as_mv_grid_fpel[1]);
hme_init_mv_grid(&ps_frm_ctxt->as_mv_grid_qpel[0]);
hme_init_mv_grid(&ps_frm_ctxt->as_mv_grid_qpel[1]);
}
ps_frm_ctxt->apu1_ref_bits_tlu_lc[0] = &ps_frm_ctxt->au1_ref_bits_tlu_lc[0][0];
ps_frm_ctxt->apu1_ref_bits_tlu_lc[1] = &ps_frm_ctxt->au1_ref_bits_tlu_lc[1][0];
}
}
/* since same layer desc pointer is stored in all the threads ctxt */
/* layer init is done only using 0th thread ctxt */
ps_ctxt = ps_master_ctxt->aps_me_ctxt[0];
ps_frm_ctxt = ps_ctxt->aps_me_frm_prms[0];
/* Initialize all layers descriptors to have -1 = poc meaning unfilled */
for(i = 0; i < (ps_frm_ctxt->max_num_ref * ps_master_ctxt->i4_num_me_frm_pllel) + 1; i++)
{
/* only enocde layer is processed */
for(j = 0; j < 1; j++)
{
layer_ctxt_t *ps_layer;
ps_layer = ps_ctxt->as_ref_descr[i].aps_layers[j];
ps_layer->i4_poc = INVALID_POC;
ps_layer->i4_is_free = 1;
ps_layer->ppu1_list_inp = &ps_frm_ctxt->apu1_list_inp[j][0];
ps_layer->ppu1_list_rec_fxfy = &ps_frm_ctxt->apu1_list_rec_fxfy[j][0];
ps_layer->ppu1_list_rec_hxfy = &ps_frm_ctxt->apu1_list_rec_hxfy[j][0];
ps_layer->ppu1_list_rec_fxhy = &ps_frm_ctxt->apu1_list_rec_fxhy[j][0];
ps_layer->ppu1_list_rec_hxhy = &ps_frm_ctxt->apu1_list_rec_hxhy[j][0];
ps_layer->ppv_dep_mngr_recon = &ps_frm_ctxt->apv_list_dep_mngr[j][0];
memset(
ps_layer->s_global_mv,
0,
sizeof(hme_mv_t) * ps_frm_ctxt->max_num_ref * NUM_GMV_LOBES);
}
}
}
/**
*******************************************************************************
* @fn S32 hme_enc_init(hme_memtab_t *ps_memtabs, hme_init_prms_t *ps_prms,rc_quant_t *ps_rc_quant_ctxt)
*
* @brief Initialises the Encode Layer HME ctxt
*
* @param[out] ps_memtabs : Pointer to an array of memtabs where module fills
* up its requirements of memory
*
* @param[in] ps_prms : Input parameters to module crucial in calculating reqd
* amt of memory
*
* @return Number of memtabs required
*******************************************************************************
*/
S32 hme_enc_init(
void *pv_ctxt,
hme_memtab_t *ps_memtabs,
hme_init_prms_t *ps_prms,
rc_quant_t *ps_rc_quant_ctxt,
WORD32 i4_num_me_frm_pllel)
{
S32 num, tot;
me_master_ctxt_t *ps_ctxt = (me_master_ctxt_t *)pv_ctxt;
tot = hme_enc_num_alloc(i4_num_me_frm_pllel);
/* Validation of init params */
if(-1 == hme_validate_init_prms(ps_prms))
return (-1);
num = hme_enc_alloc_init_mem(ps_memtabs, ps_prms, pv_ctxt, 1, i4_num_me_frm_pllel);
if(num > tot)
return (-1);
/* Initialize all enumerations based globals */
//hme_init_globals(); /* done as part of coarse me */
/* Copy the memtabs into the context for returning during free */
memcpy(ps_ctxt->as_memtabs, ps_memtabs, sizeof(hme_memtab_t) * tot);
/* initialize the context and related buffers */
hme_enc_init_ctxt(ps_ctxt, ps_prms, ps_rc_quant_ctxt);
return (0);
}
/**
*******************************************************************************
* @fn S32 hme_coarse_init(hme_memtab_t *ps_memtabs, hme_init_prms_t *ps_prms)
*
* @brief Initialises the Coarse HME ctxt
*
* @param[out] ps_memtabs : Pointer to an array of memtabs where module fills
* up its requirements of memory
*
* @param[in] ps_prms : Input parameters to module crucial in calculating reqd
* amt of memory
*
* @return Number of memtabs required
*******************************************************************************
*/
S32 hme_coarse_init(void *pv_ctxt, hme_memtab_t *ps_memtabs, hme_init_prms_t *ps_prms)
{
S32 num, tot;
coarse_me_master_ctxt_t *ps_ctxt = (coarse_me_master_ctxt_t *)pv_ctxt;
tot = hme_coarse_num_alloc();
/* Validation of init params */
if(-1 == hme_validate_init_prms(ps_prms))
return (-1);
num = hme_coarse_alloc_init_mem(ps_memtabs, ps_prms, pv_ctxt, 1);
if(num > tot)
return (-1);
/* Initialize all enumerations based globals */
hme_init_globals();
/* Copy the memtabs into the context for returning during free */
memcpy(ps_ctxt->as_memtabs, ps_memtabs, sizeof(hme_memtab_t) * tot);
/* initialize the context and related buffers */
hme_coarse_init_ctxt(ps_ctxt, ps_prms);
return (0);
}
/**
*******************************************************************************
* @fn S32 hme_set_resolution(void *pv_me_ctxt,
* S32 n_enc_layers,
* S32 *p_wd,
* S32 *p_ht
*
* @brief Sets up the layers based on resolution information.
*
* @param[in, out] pv_me_ctxt : ME handle, updated with the resolution info
*
* @param[in] n_enc_layers : Number of layers encoded
*
* @param[in] p_wd : Pointer to an array having widths for each encode layer
*
* @param[in] p_ht : Pointer to an array having heights for each encode layer
*
* @return void
*******************************************************************************
*/
void hme_set_resolution(void *pv_me_ctxt, S32 n_enc_layers, S32 *p_wd, S32 *p_ht, S32 me_frm_id)
{
S32 n_tot_layers, num_layers_explicit_search, i, j;
me_ctxt_t *ps_thrd_ctxt;
me_frm_ctxt_t *ps_ctxt;
S32 a_wd[MAX_NUM_LAYERS], a_ht[MAX_NUM_LAYERS];
S32 a_disp_wd[MAX_NUM_LAYERS], a_disp_ht[MAX_NUM_LAYERS];
memcpy(a_wd, p_wd, n_enc_layers * sizeof(S32));
memcpy(a_ht, p_ht, n_enc_layers * sizeof(S32));
ps_thrd_ctxt = (me_ctxt_t *)pv_me_ctxt;
ps_ctxt = ps_thrd_ctxt->aps_me_frm_prms[me_frm_id];
/*************************************************************************/
/* Derive the number of HME layers, including both encoded and non encode*/
/* This function also derives the width and ht of each layer. */
/*************************************************************************/
n_tot_layers = hme_derive_num_layers(n_enc_layers, a_wd, a_ht, a_disp_wd, a_disp_ht);
num_layers_explicit_search = ps_thrd_ctxt->s_init_prms.num_layers_explicit_search;
if(num_layers_explicit_search <= 0)
num_layers_explicit_search = n_tot_layers - 1;
num_layers_explicit_search = MIN(num_layers_explicit_search, n_tot_layers - 1);
ps_ctxt->num_layers_explicit_search = num_layers_explicit_search;
memset(ps_ctxt->u1_encode, 0, n_tot_layers);
memset(ps_ctxt->u1_encode, 1, n_enc_layers);
/* only encode layer should be processed */
ps_ctxt->num_layers = n_tot_layers;
ps_ctxt->i4_wd = a_wd[0];
ps_ctxt->i4_ht = a_ht[0];
/* Memtabs : Layers * num-ref + 1 */
for(i = 0; i < ps_ctxt->max_num_ref + 1; i++)
{
for(j = 0; j < 1; j++)
{
S32 wd, ht;
layer_ctxt_t *ps_layer;
U08 u1_enc = ps_ctxt->u1_encode[j];
wd = a_wd[j];
ht = a_ht[j];
ps_layer = ps_thrd_ctxt->as_ref_descr[i].aps_layers[j];
hme_set_layer_res_attrs(ps_layer, wd, ht, a_disp_wd[j], a_disp_ht[j], u1_enc);
}
}
}
/**
*******************************************************************************
* @fn S32 hme_coarse_set_resolution(void *pv_me_ctxt,
* S32 n_enc_layers,
* S32 *p_wd,
* S32 *p_ht
*
* @brief Sets up the layers based on resolution information.
*
* @param[in, out] pv_me_ctxt : ME handle, updated with the resolution info
*
* @param[in] n_enc_layers : Number of layers encoded
*
* @param[in] p_wd : Pointer to an array having widths for each encode layer
*
* @param[in] p_ht : Pointer to an array having heights for each encode layer
*
* @return void
*******************************************************************************
*/
void hme_coarse_set_resolution(void *pv_me_ctxt, S32 n_enc_layers, S32 *p_wd, S32 *p_ht)
{
S32 n_tot_layers, num_layers_explicit_search, i, j;
coarse_me_ctxt_t *ps_ctxt;
S32 a_wd[MAX_NUM_LAYERS], a_ht[MAX_NUM_LAYERS];
S32 a_disp_wd[MAX_NUM_LAYERS], a_disp_ht[MAX_NUM_LAYERS];
memcpy(a_wd, p_wd, n_enc_layers * sizeof(S32));
memcpy(a_ht, p_ht, n_enc_layers * sizeof(S32));
ps_ctxt = (coarse_me_ctxt_t *)pv_me_ctxt;
/*************************************************************************/
/* Derive the number of HME layers, including both encoded and non encode*/
/* This function also derives the width and ht of each layer. */
/*************************************************************************/
n_tot_layers = hme_derive_num_layers(n_enc_layers, a_wd, a_ht, a_disp_wd, a_disp_ht);
num_layers_explicit_search = ps_ctxt->s_init_prms.num_layers_explicit_search;
if(num_layers_explicit_search <= 0)
num_layers_explicit_search = n_tot_layers - 1;
num_layers_explicit_search = MIN(num_layers_explicit_search, n_tot_layers - 1);
ps_ctxt->num_layers_explicit_search = num_layers_explicit_search;
memset(ps_ctxt->u1_encode, 0, n_tot_layers);
memset(ps_ctxt->u1_encode, 1, n_enc_layers);
/* encode layer should be excluded */
ps_ctxt->num_layers = n_tot_layers;
memcpy(ps_ctxt->a_wd, a_wd, sizeof(S32) * n_tot_layers);
memcpy(ps_ctxt->a_ht, a_ht, sizeof(S32) * n_tot_layers);
/* Memtabs : Layers * num-ref + 1 */
for(i = 0; i < ps_ctxt->max_num_ref + 1 + NUM_BUFS_DECOMP_HME; i++)
{
for(j = 1; j < n_tot_layers; j++)
{
S32 wd, ht;
layer_ctxt_t *ps_layer;
U08 u1_enc = ps_ctxt->u1_encode[j];
wd = a_wd[j];
ht = a_ht[j];
ps_layer = ps_ctxt->as_ref_descr[i].aps_layers[j];
hme_set_layer_res_attrs(ps_layer, wd, ht, a_disp_wd[j], a_disp_ht[j], u1_enc);
}
}
}
S32 hme_find_descr_idx(me_ctxt_t *ps_ctxt, S32 i4_poc, S32 i4_idr_gop_num, S32 i4_num_me_frm_pllel)
{
S32 i;
for(i = 0; i < (ps_ctxt->aps_me_frm_prms[0]->max_num_ref * i4_num_me_frm_pllel) + 1; i++)
{
if(ps_ctxt->as_ref_descr[i].aps_layers[0]->i4_poc == i4_poc &&
ps_ctxt->as_ref_descr[i].aps_layers[0]->i4_idr_gop_num == i4_idr_gop_num)
return i;
}
/* Should not come here */
ASSERT(0);
return (-1);
}
S32 hme_coarse_find_descr_idx(coarse_me_ctxt_t *ps_ctxt, S32 i4_poc)
{
S32 i;
for(i = 0; i < ps_ctxt->max_num_ref + 1 + NUM_BUFS_DECOMP_HME; i++)
{
if(ps_ctxt->as_ref_descr[i].aps_layers[1]->i4_poc == i4_poc)
return i;
}
/* Should not come here */
ASSERT(0);
return (-1);
}
S32 hme_find_free_descr_idx(me_ctxt_t *ps_ctxt, S32 i4_num_me_frm_pllel)
{
S32 i;
for(i = 0; i < (ps_ctxt->aps_me_frm_prms[0]->max_num_ref * i4_num_me_frm_pllel) + 1; i++)
{
if(ps_ctxt->as_ref_descr[i].aps_layers[0]->i4_is_free == 1)
{
ps_ctxt->as_ref_descr[i].aps_layers[0]->i4_is_free = 0;
return i;
}
}
/* Should not come here */
ASSERT(0);
return (-1);
}
S32 hme_coarse_find_free_descr_idx(void *pv_ctxt)
{
S32 i;
coarse_me_ctxt_t *ps_ctxt = (coarse_me_ctxt_t *)pv_ctxt;
for(i = 0; i < ps_ctxt->max_num_ref + 1 + NUM_BUFS_DECOMP_HME; i++)
{
if(ps_ctxt->as_ref_descr[i].aps_layers[1]->i4_poc == -1)
return i;
}
/* Should not come here */
ASSERT(0);
return (-1);
}
void hme_discard_frm(
void *pv_me_ctxt, S32 *p_pocs_to_remove, S32 i4_idr_gop_num, S32 i4_num_me_frm_pllel)
{
me_ctxt_t *ps_ctxt = (me_ctxt_t *)pv_me_ctxt;
S32 count = 0, idx, i;
layers_descr_t *ps_descr;
/* Search for the id of the layer descriptor that has this poc */
while(p_pocs_to_remove[count] != INVALID_POC)
{
ASSERT(count == 0);
idx = hme_find_descr_idx(
ps_ctxt, p_pocs_to_remove[count], i4_idr_gop_num, i4_num_me_frm_pllel);
ps_descr = &ps_ctxt->as_ref_descr[idx];
/*********************************************************************/
/* Setting i4_is_free = 1 in all layers invalidates this layer ctxt */
/* Now this can be used for a fresh picture. */
/*********************************************************************/
for(i = 0; i < 1; i++)
{
ps_descr->aps_layers[i]->i4_is_free = 1;
}
count++;
}
}
void hme_coarse_discard_frm(void *pv_me_ctxt, S32 *p_pocs_to_remove)
{
coarse_me_ctxt_t *ps_ctxt = (coarse_me_ctxt_t *)pv_me_ctxt;
S32 count = 0, idx, i;
layers_descr_t *ps_descr;
/* Search for the id of the layer descriptor that has this poc */
while(p_pocs_to_remove[count] != -1)
{
idx = hme_coarse_find_descr_idx(ps_ctxt, p_pocs_to_remove[count]);
ps_descr = &ps_ctxt->as_ref_descr[idx];
/*********************************************************************/
/* Setting poc = -1 in all layers invalidates this layer ctxt */
/* Now this can be used for a fresh picture. */
/*********************************************************************/
for(i = 1; i < ps_ctxt->num_layers; i++)
{
ps_descr->aps_layers[i]->i4_poc = -1;
}
count++;
}
}
void hme_update_layer_desc(
layers_descr_t *ps_layers_desc,
hme_ref_desc_t *ps_ref_desc,
S32 start_lyr_id,
S32 num_layers,
layers_descr_t *ps_curr_desc)
{
layer_ctxt_t *ps_layer_ctxt, *ps_curr_layer;
S32 i;
for(i = start_lyr_id; i < num_layers; i++)
{
ps_layer_ctxt = ps_layers_desc->aps_layers[i];
ps_curr_layer = ps_curr_desc->aps_layers[i];
ps_layer_ctxt->i4_poc = ps_ref_desc->i4_poc;
ps_layer_ctxt->i4_idr_gop_num = ps_ref_desc->i4_GOP_num;
/* Copy the recon planes for the given reference pic at given layer */
ps_layer_ctxt->pu1_rec_fxfy = ps_ref_desc->as_ref_info[i].pu1_rec_fxfy;
ps_layer_ctxt->pu1_rec_hxfy = ps_ref_desc->as_ref_info[i].pu1_rec_hxfy;
ps_layer_ctxt->pu1_rec_fxhy = ps_ref_desc->as_ref_info[i].pu1_rec_fxhy;
ps_layer_ctxt->pu1_rec_hxhy = ps_ref_desc->as_ref_info[i].pu1_rec_hxhy;
/*********************************************************************/
/* reconstruction strides, offsets and padding info are copied for */
/* this reference pic. It is assumed that these will be same across */
/* pics, so even the current pic has this info updated, though the */
/* current pic still does not have valid recon pointers. */
/*********************************************************************/
ps_layer_ctxt->i4_rec_stride = ps_ref_desc->as_ref_info[i].luma_stride;
ps_layer_ctxt->i4_rec_offset = ps_ref_desc->as_ref_info[i].luma_offset;
ps_layer_ctxt->i4_pad_x_rec = ps_ref_desc->as_ref_info[i].u1_pad_x;
ps_layer_ctxt->i4_pad_y_rec = ps_ref_desc->as_ref_info[i].u1_pad_y;
ps_curr_layer->i4_rec_stride = ps_ref_desc->as_ref_info[i].luma_stride;
ps_curr_layer->i4_pad_x_rec = ps_ref_desc->as_ref_info[i].u1_pad_x;
ps_curr_layer->i4_pad_y_rec = ps_ref_desc->as_ref_info[i].u1_pad_y;
}
}
void hme_add_inp(void *pv_me_ctxt, hme_inp_desc_t *ps_inp_desc, S32 me_frm_id, S32 i4_thrd_id)
{
layers_descr_t *ps_desc;
layer_ctxt_t *ps_layer_ctxt;
me_master_ctxt_t *ps_master_ctxt = (me_master_ctxt_t *)pv_me_ctxt;
me_ctxt_t *ps_thrd_ctxt;
me_frm_ctxt_t *ps_ctxt;
hme_inp_buf_attr_t *ps_attr;
S32 i4_poc, idx, i, i4_prev_poc;
S32 num_thrds, prev_me_frm_id;
S32 i4_idr_gop_num, i4_is_reference;
/* since same layer desc pointer is stored in all thread ctxt */
/* a free idx is obtained using 0th thread ctxt pointer */
ps_thrd_ctxt = ps_master_ctxt->aps_me_ctxt[i4_thrd_id];
ps_ctxt = ps_thrd_ctxt->aps_me_frm_prms[me_frm_id];
/* Deriving the previous poc from previous frames context */
if(me_frm_id == 0)
prev_me_frm_id = (MAX_NUM_ME_PARALLEL - 1);
else
prev_me_frm_id = me_frm_id - 1;
i4_prev_poc = ps_thrd_ctxt->aps_me_frm_prms[prev_me_frm_id]->i4_curr_poc;
/* Obtain an empty layer descriptor */
idx = hme_find_free_descr_idx(ps_thrd_ctxt, ps_master_ctxt->i4_num_me_frm_pllel);
ps_desc = &ps_thrd_ctxt->as_ref_descr[idx];
/* initialise the parameters for all the threads */
for(num_thrds = 0; num_thrds < ps_master_ctxt->i4_num_proc_thrds; num_thrds++)
{
me_frm_ctxt_t *ps_tmp_frm_ctxt;
ps_thrd_ctxt = ps_master_ctxt->aps_me_ctxt[num_thrds];
ps_tmp_frm_ctxt = ps_thrd_ctxt->aps_me_frm_prms[me_frm_id];
ps_tmp_frm_ctxt->ps_curr_descr = &ps_thrd_ctxt->as_ref_descr[idx];
/* Do the initialization for the first thread alone */
i4_poc = ps_inp_desc->i4_poc;
i4_idr_gop_num = ps_inp_desc->i4_idr_gop_num;
i4_is_reference = ps_inp_desc->i4_is_reference;
/*Update poc id of previously encoded frm and curr frm */
ps_tmp_frm_ctxt->i4_prev_poc = i4_prev_poc;
ps_tmp_frm_ctxt->i4_curr_poc = i4_poc;
}
/* since same layer desc pointer is stored in all thread ctxt */
/* following processing is done using 0th thread ctxt pointer */
ps_thrd_ctxt = ps_master_ctxt->aps_me_ctxt[0];
/* only encode layer */
for(i = 0; i < 1; i++)
{
ps_layer_ctxt = ps_desc->aps_layers[i];
ps_attr = &ps_inp_desc->s_layer_desc[i];
ps_layer_ctxt->i4_poc = i4_poc;
ps_layer_ctxt->i4_idr_gop_num = i4_idr_gop_num;
ps_layer_ctxt->i4_is_reference = i4_is_reference;
ps_layer_ctxt->i4_non_ref_free = 0;
/* If this layer is encoded, copy input attributes */
if(ps_ctxt->u1_encode[i])
{
ps_layer_ctxt->pu1_inp = ps_attr->pu1_y;
ps_layer_ctxt->i4_inp_stride = ps_attr->luma_stride;
ps_layer_ctxt->i4_pad_x_inp = 0;
ps_layer_ctxt->i4_pad_y_inp = 0;
}
else
{
/* If not encoded, then ME owns the buffer.*/
S32 wd, dst_stride;
ASSERT(i != 0);
wd = ps_ctxt->i4_wd;
/* destination has padding on either side of 16 */
dst_stride = CEIL16((wd >> 1)) + 32 + 4;
ps_layer_ctxt->i4_inp_stride = dst_stride;
}
}
return;
}
void hme_coarse_add_inp(void *pv_me_ctxt, hme_inp_desc_t *ps_inp_desc, WORD32 i4_curr_idx)
{
layers_descr_t *ps_desc;
layer_ctxt_t *ps_layer_ctxt;
coarse_me_master_ctxt_t *ps_master_ctxt = (coarse_me_master_ctxt_t *)pv_me_ctxt;
coarse_me_ctxt_t *ps_ctxt;
hme_inp_buf_attr_t *ps_attr;
S32 i4_poc, i;
S32 num_thrds;
/* since same layer desc pointer is stored in all thread ctxt */
/* a free idx is obtained using 0th thread ctxt pointer */
ps_ctxt = ps_master_ctxt->aps_me_ctxt[0];
ps_desc = &ps_ctxt->as_ref_descr[i4_curr_idx];
/* initialise the parameters for all the threads */
for(num_thrds = 0; num_thrds < ps_master_ctxt->i4_num_proc_thrds; num_thrds++)
{
ps_ctxt = ps_master_ctxt->aps_me_ctxt[num_thrds];
ps_ctxt->ps_curr_descr = &ps_ctxt->as_ref_descr[i4_curr_idx];
i4_poc = ps_inp_desc->i4_poc;
/*Update poc id of previously encoded frm and curr frm */
ps_ctxt->i4_prev_poc = ps_ctxt->i4_curr_poc;
ps_ctxt->i4_curr_poc = i4_poc;
}
/* since same layer desc pointer is stored in all thread ctxt */
/* following processing is done using 0th thread ctxt pointer */
ps_ctxt = ps_master_ctxt->aps_me_ctxt[0];
/* only non encode layer */
for(i = 1; i < ps_ctxt->num_layers; i++)
{
ps_layer_ctxt = ps_desc->aps_layers[i];
ps_attr = &ps_inp_desc->s_layer_desc[i];
ps_layer_ctxt->i4_poc = i4_poc;
/* If this layer is encoded, copy input attributes */
if(ps_ctxt->u1_encode[i])
{
ps_layer_ctxt->pu1_inp = ps_attr->pu1_y;
ps_layer_ctxt->i4_inp_stride = ps_attr->luma_stride;
ps_layer_ctxt->i4_pad_x_inp = 0;
ps_layer_ctxt->i4_pad_y_inp = 0;
}
else
{
/* If not encoded, then ME owns the buffer. */
/* decomp of lower layers happens on a seperate pass */
/* Coarse Me should export the pointers to the caller */
S32 wd, dst_stride;
ASSERT(i != 0);
wd = ps_ctxt->a_wd[i - 1];
/* destination has padding on either side of 16 */
dst_stride = CEIL16((wd >> 1)) + 32 + 4;
ps_layer_ctxt->i4_inp_stride = dst_stride;
}
}
}
static __inline U08 hme_determine_num_results_per_part(
U08 u1_layer_id, U08 u1_num_layers, ME_QUALITY_PRESETS_T e_quality_preset)
{
U08 u1_num_results_per_part = MAX_RESULTS_PER_PART;
if((u1_layer_id == 0) && !!RESTRICT_NUM_PARTITION_LEVEL_L0ME_RESULTS_TO_1)
{
switch(e_quality_preset)
{
case ME_XTREME_SPEED_25:
case ME_XTREME_SPEED:
case ME_HIGH_SPEED:
case ME_MEDIUM_SPEED:
case ME_HIGH_QUALITY:
case ME_PRISTINE_QUALITY:
{
u1_num_results_per_part = 1;
break;
}
default:
{
u1_num_results_per_part = MAX_RESULTS_PER_PART;
break;
}
}
}
else if((u1_layer_id == 1) && !!RESTRICT_NUM_PARTITION_LEVEL_L1ME_RESULTS_TO_1)
{
switch(e_quality_preset)
{
case ME_XTREME_SPEED_25:
case ME_HIGH_QUALITY:
case ME_PRISTINE_QUALITY:
{
u1_num_results_per_part = 1;
break;
}
default:
{
u1_num_results_per_part = MAX_RESULTS_PER_PART;
break;
}
}
}
else if((u1_layer_id == 2) && (u1_num_layers > 3) && !!RESTRICT_NUM_PARTITION_LEVEL_L2ME_RESULTS_TO_1)
{
switch(e_quality_preset)
{
case ME_XTREME_SPEED_25:
case ME_XTREME_SPEED:
case ME_HIGH_SPEED:
case ME_MEDIUM_SPEED:
{
u1_num_results_per_part = 1;
break;
}
default:
{
u1_num_results_per_part = MAX_RESULTS_PER_PART;
break;
}
}
}
return u1_num_results_per_part;
}
static __inline void hme_max_search_cands_per_search_cand_loc_populator(
hme_frm_prms_t *ps_frm_prms,
U08 *pu1_num_fpel_search_cands,
U08 u1_layer_id,
ME_QUALITY_PRESETS_T e_quality_preset)
{
if(0 == u1_layer_id)
{
S32 i;
for(i = 0; i < NUM_SEARCH_CAND_LOCATIONS; i++)
{
switch(e_quality_preset)
{
#if RESTRICT_NUM_SEARCH_CANDS_PER_SEARCH_CAND_LOC
case ME_XTREME_SPEED_25:
case ME_XTREME_SPEED:
case ME_HIGH_SPEED:
case ME_MEDIUM_SPEED:
{
pu1_num_fpel_search_cands[i] = 1;
break;
}
#endif
default:
{
pu1_num_fpel_search_cands[i] =
MAX(2,
MAX(ps_frm_prms->u1_num_active_ref_l0, ps_frm_prms->u1_num_active_ref_l1) *
((COLOCATED == (SEARCH_CAND_LOCATIONS_T)i) + 1));
break;
}
}
}
}
}
static __inline U08
hme_determine_max_2nx2n_tu_recur_cands(U08 u1_layer_id, ME_QUALITY_PRESETS_T e_quality_preset)
{
U08 u1_num_cands = 2;
if((u1_layer_id == 0) && !!RESTRICT_NUM_2NX2N_TU_RECUR_CANDS)
{
switch(e_quality_preset)
{
case ME_XTREME_SPEED_25:
case ME_XTREME_SPEED:
case ME_HIGH_SPEED:
case ME_MEDIUM_SPEED:
{
u1_num_cands = 1;
break;
}
default:
{
u1_num_cands = 2;
break;
}
}
}
return u1_num_cands;
}
static __inline U08
hme_determine_max_num_fpel_refine_centers(U08 u1_layer_id, ME_QUALITY_PRESETS_T e_quality_preset)
{
U08 i;
U08 u1_num_centers = 0;
if(0 == u1_layer_id)
{
switch(e_quality_preset)
{
case ME_XTREME_SPEED_25:
{
for(i = 0; i < TOT_NUM_PARTS; i++)
{
u1_num_centers += gau1_num_best_results_XS25[i];
}
break;
}
case ME_XTREME_SPEED:
{
for(i = 0; i < TOT_NUM_PARTS; i++)
{
u1_num_centers += gau1_num_best_results_XS[i];
}
break;
}
case ME_HIGH_SPEED:
{
for(i = 0; i < TOT_NUM_PARTS; i++)
{
u1_num_centers += gau1_num_best_results_HS[i];
}
break;
}
case ME_MEDIUM_SPEED:
{
for(i = 0; i < TOT_NUM_PARTS; i++)
{
u1_num_centers += gau1_num_best_results_MS[i];
}
break;
}
case ME_HIGH_QUALITY:
{
for(i = 0; i < TOT_NUM_PARTS; i++)
{
u1_num_centers += gau1_num_best_results_HQ[i];
}
break;
}
case ME_PRISTINE_QUALITY:
{
for(i = 0; i < TOT_NUM_PARTS; i++)
{
u1_num_centers += gau1_num_best_results_PQ[i];
}
break;
}
}
}
return u1_num_centers;
}
static __inline U08 hme_determine_max_num_subpel_refine_centers(
U08 u1_layer_id, U08 u1_max_2Nx2N_subpel_cands, U08 u1_max_NxN_subpel_cands)
{
U08 u1_num_centers = 0;
if(0 == u1_layer_id)
{
u1_num_centers += u1_max_2Nx2N_subpel_cands + 4 * u1_max_NxN_subpel_cands;
}
return u1_num_centers;
}
void hme_set_refine_prms(
void *pv_refine_prms,
U08 u1_encode,
S32 num_ref,
S32 layer_id,
S32 num_layers,
S32 num_layers_explicit_search,
S32 use_4x4,
hme_frm_prms_t *ps_frm_prms,
double **ppd_intra_costs,
me_coding_params_t *ps_me_coding_tools)
{
refine_prms_t *ps_refine_prms = (refine_prms_t *)pv_refine_prms;
ps_refine_prms->i4_encode = u1_encode;
ps_refine_prms->bidir_enabled = ps_frm_prms->bidir_enabled;
ps_refine_prms->i4_layer_id = layer_id;
/*************************************************************************/
/* Refinement layers have two lambdas, one for closed loop, another for */
/* open loop. Non encode layers use only open loop lambda. */
/*************************************************************************/
ps_refine_prms->lambda_inp = ps_frm_prms->i4_ol_sad_lambda_qf;
ps_refine_prms->lambda_recon = ps_frm_prms->i4_cl_sad_lambda_qf;
ps_refine_prms->lambda_q_shift = ps_frm_prms->lambda_q_shift;
ps_refine_prms->lambda_inp =
((float)ps_refine_prms->lambda_inp) * (100.0f - ME_LAMBDA_DISCOUNT) / 100.0f;
ps_refine_prms->lambda_recon =
((float)ps_refine_prms->lambda_recon) * (100.0f - ME_LAMBDA_DISCOUNT) / 100.0f;
if((u1_encode) && (NULL != ppd_intra_costs))
{
ps_refine_prms->pd_intra_costs = ppd_intra_costs[layer_id];
}
/* Explicit or implicit depends on number of layers having eplicit search */
if((layer_id == 0) || (num_layers - layer_id > num_layers_explicit_search))
{
ps_refine_prms->explicit_ref = 0;
ps_refine_prms->i4_num_ref_fpel = MIN(2, num_ref);
}
else
{
ps_refine_prms->explicit_ref = 1;
ps_refine_prms->i4_num_ref_fpel = num_ref;
}
ps_refine_prms->e_search_complexity = SEARCH_CX_HIGH;
ps_refine_prms->i4_num_steps_hpel_refine = ps_me_coding_tools->i4_num_steps_hpel_refine;
ps_refine_prms->i4_num_steps_qpel_refine = ps_me_coding_tools->i4_num_steps_qpel_refine;
if(u1_encode)
{
ps_refine_prms->i4_num_mvbank_results = 1;
ps_refine_prms->i4_use_rec_in_fpel = 1;
ps_refine_prms->i4_num_steps_fpel_refine = 1;
if(ps_me_coding_tools->e_me_quality_presets == ME_PRISTINE_QUALITY)
{
ps_refine_prms->i4_num_fpel_results = 4;
ps_refine_prms->i4_num_32x32_merge_results = 4;
ps_refine_prms->i4_num_64x64_merge_results = 4;
ps_refine_prms->i4_num_steps_post_refine_fpel = 3;
ps_refine_prms->i4_use_satd_subpel = 1;
ps_refine_prms->u1_max_subpel_candts_2Nx2N = 2;
ps_refine_prms->u1_max_subpel_candts_NxN = 1;
ps_refine_prms->u1_subpel_candt_threshold = 1;
ps_refine_prms->e_search_complexity = SEARCH_CX_MED;
ps_refine_prms->pu1_num_best_results = gau1_num_best_results_PQ;
ps_refine_prms->limit_active_partitions = 0;
}
else if(ps_me_coding_tools->e_me_quality_presets == ME_HIGH_QUALITY)
{
ps_refine_prms->i4_num_fpel_results = 4;
ps_refine_prms->i4_num_32x32_merge_results = 4;
ps_refine_prms->i4_num_64x64_merge_results = 4;
ps_refine_prms->i4_num_steps_post_refine_fpel = 3;
ps_refine_prms->i4_use_satd_subpel = 1;
ps_refine_prms->u1_max_subpel_candts_2Nx2N = 2;
ps_refine_prms->u1_max_subpel_candts_NxN = 1;
ps_refine_prms->u1_subpel_candt_threshold = 2;
ps_refine_prms->e_search_complexity = SEARCH_CX_MED;
ps_refine_prms->pu1_num_best_results = gau1_num_best_results_HQ;
ps_refine_prms->limit_active_partitions = 0;
}
else if(ps_me_coding_tools->e_me_quality_presets == ME_MEDIUM_SPEED)
{
ps_refine_prms->i4_num_fpel_results = 1;
ps_refine_prms->i4_num_32x32_merge_results = 2;
ps_refine_prms->i4_num_64x64_merge_results = 2;
ps_refine_prms->i4_num_steps_post_refine_fpel = 0;
ps_refine_prms->i4_use_satd_subpel = 1;
ps_refine_prms->u1_max_subpel_candts_2Nx2N = 2;
ps_refine_prms->u1_max_subpel_candts_NxN = 1;
ps_refine_prms->u1_subpel_candt_threshold = 3;
ps_refine_prms->e_search_complexity = SEARCH_CX_MED;
ps_refine_prms->pu1_num_best_results = gau1_num_best_results_MS;
ps_refine_prms->limit_active_partitions = 1;
}
else if(ps_me_coding_tools->e_me_quality_presets == ME_HIGH_SPEED)
{
ps_refine_prms->i4_num_fpel_results = 1;
ps_refine_prms->i4_num_32x32_merge_results = 2;
ps_refine_prms->i4_num_64x64_merge_results = 2;
ps_refine_prms->i4_num_steps_post_refine_fpel = 0;
ps_refine_prms->u1_max_subpel_candts_2Nx2N = 1;
ps_refine_prms->u1_max_subpel_candts_NxN = 1;
ps_refine_prms->i4_use_satd_subpel = 0;
ps_refine_prms->u1_subpel_candt_threshold = 0;
ps_refine_prms->e_search_complexity = SEARCH_CX_MED;
ps_refine_prms->pu1_num_best_results = gau1_num_best_results_HS;
ps_refine_prms->limit_active_partitions = 1;
}
else if(ps_me_coding_tools->e_me_quality_presets == ME_XTREME_SPEED)
{
ps_refine_prms->i4_num_fpel_results = 1;
ps_refine_prms->i4_num_32x32_merge_results = 2;
ps_refine_prms->i4_num_64x64_merge_results = 2;
ps_refine_prms->i4_num_steps_post_refine_fpel = 0;
ps_refine_prms->i4_use_satd_subpel = 0;
ps_refine_prms->u1_max_subpel_candts_2Nx2N = 1;
ps_refine_prms->u1_max_subpel_candts_NxN = 0;
ps_refine_prms->u1_subpel_candt_threshold = 0;
ps_refine_prms->e_search_complexity = SEARCH_CX_MED;
ps_refine_prms->pu1_num_best_results = gau1_num_best_results_XS;
ps_refine_prms->limit_active_partitions = 1;
}
else if(ps_me_coding_tools->e_me_quality_presets == ME_XTREME_SPEED_25)
{
ps_refine_prms->i4_num_fpel_results = 1;
ps_refine_prms->i4_num_32x32_merge_results = 2;
ps_refine_prms->i4_num_64x64_merge_results = 2;
ps_refine_prms->i4_num_steps_post_refine_fpel = 0;
ps_refine_prms->i4_use_satd_subpel = 0;
ps_refine_prms->u1_max_subpel_candts_2Nx2N = 1;
ps_refine_prms->u1_max_subpel_candts_NxN = 0;
ps_refine_prms->u1_subpel_candt_threshold = 0;
ps_refine_prms->e_search_complexity = SEARCH_CX_LOW;
ps_refine_prms->pu1_num_best_results = gau1_num_best_results_XS25;
ps_refine_prms->limit_active_partitions = 1;
}
}
else
{
ps_refine_prms->i4_num_fpel_results = 2;
ps_refine_prms->i4_use_rec_in_fpel = 0;
ps_refine_prms->i4_num_steps_fpel_refine = 1;
ps_refine_prms->i4_num_steps_hpel_refine = 0;
ps_refine_prms->i4_num_steps_qpel_refine = 0;
if(ps_me_coding_tools->e_me_quality_presets == ME_HIGH_SPEED)
{
ps_refine_prms->i4_num_steps_post_refine_fpel = 0;
ps_refine_prms->i4_use_satd_subpel = 1;
ps_refine_prms->e_search_complexity = SEARCH_CX_LOW;
ps_refine_prms->pu1_num_best_results = gau1_num_best_results_HS;
}
else if(ps_me_coding_tools->e_me_quality_presets == ME_XTREME_SPEED)
{
ps_refine_prms->i4_num_steps_post_refine_fpel = 0;
ps_refine_prms->i4_use_satd_subpel = 0;
ps_refine_prms->e_search_complexity = SEARCH_CX_LOW;
ps_refine_prms->pu1_num_best_results = gau1_num_best_results_XS;
}
else if(ps_me_coding_tools->e_me_quality_presets == ME_XTREME_SPEED_25)
{
ps_refine_prms->i4_num_steps_post_refine_fpel = 0;
ps_refine_prms->i4_use_satd_subpel = 0;
ps_refine_prms->e_search_complexity = SEARCH_CX_LOW;
ps_refine_prms->pu1_num_best_results = gau1_num_best_results_XS25;
}
else if(ps_me_coding_tools->e_me_quality_presets == ME_PRISTINE_QUALITY)
{
ps_refine_prms->i4_num_steps_post_refine_fpel = 2;
ps_refine_prms->i4_use_satd_subpel = 1;
ps_refine_prms->e_search_complexity = SEARCH_CX_MED;
ps_refine_prms->pu1_num_best_results = gau1_num_best_results_PQ;
}
else if(ps_me_coding_tools->e_me_quality_presets == ME_HIGH_QUALITY)
{
ps_refine_prms->i4_num_steps_post_refine_fpel = 2;
ps_refine_prms->i4_use_satd_subpel = 1;
ps_refine_prms->e_search_complexity = SEARCH_CX_MED;
ps_refine_prms->pu1_num_best_results = gau1_num_best_results_HQ;
}
else if(ps_me_coding_tools->e_me_quality_presets == ME_MEDIUM_SPEED)
{
ps_refine_prms->i4_num_steps_post_refine_fpel = 0;
ps_refine_prms->i4_use_satd_subpel = 1;
ps_refine_prms->e_search_complexity = SEARCH_CX_LOW;
ps_refine_prms->pu1_num_best_results = gau1_num_best_results_MS;
}
/* Following fields unused in the non-encode layers */
/* But setting the same to default values */
ps_refine_prms->i4_num_32x32_merge_results = 4;
ps_refine_prms->i4_num_64x64_merge_results = 4;
if(!ps_frm_prms->bidir_enabled)
{
ps_refine_prms->limit_active_partitions = 0;
}
else
{
ps_refine_prms->limit_active_partitions = 1;
}
}
ps_refine_prms->i4_enable_4x4_part =
hme_get_mv_blk_size(use_4x4, layer_id, num_layers, u1_encode);
if(!ps_me_coding_tools->u1_l0_me_controlled_via_cmd_line)
{
ps_refine_prms->i4_num_results_per_part = hme_determine_num_results_per_part(
layer_id, num_layers, ps_me_coding_tools->e_me_quality_presets);
hme_max_search_cands_per_search_cand_loc_populator(
ps_frm_prms,
ps_refine_prms->au1_num_fpel_search_cands,
layer_id,
ps_me_coding_tools->e_me_quality_presets);
ps_refine_prms->u1_max_2nx2n_tu_recur_cands = hme_determine_max_2nx2n_tu_recur_cands(
layer_id, ps_me_coding_tools->e_me_quality_presets);
ps_refine_prms->u1_max_num_fpel_refine_centers = hme_determine_max_num_fpel_refine_centers(
layer_id, ps_me_coding_tools->e_me_quality_presets);
ps_refine_prms->u1_max_num_subpel_refine_centers =
hme_determine_max_num_subpel_refine_centers(
layer_id,
ps_refine_prms->u1_max_subpel_candts_2Nx2N,
ps_refine_prms->u1_max_subpel_candts_NxN);
}
else
{
if(0 == layer_id)
{
ps_refine_prms->i4_num_results_per_part =
ps_me_coding_tools->u1_num_results_per_part_in_l0me;
}
else if(1 == layer_id)
{
ps_refine_prms->i4_num_results_per_part =
ps_me_coding_tools->u1_num_results_per_part_in_l1me;
}
else if((2 == layer_id) && (num_layers > 3))
{
ps_refine_prms->i4_num_results_per_part =
ps_me_coding_tools->u1_num_results_per_part_in_l2me;
}
else
{
ps_refine_prms->i4_num_results_per_part = hme_determine_num_results_per_part(
layer_id, num_layers, ps_me_coding_tools->e_me_quality_presets);
}
memset(
ps_refine_prms->au1_num_fpel_search_cands,
ps_me_coding_tools->u1_max_num_coloc_cands,
sizeof(ps_refine_prms->au1_num_fpel_search_cands));
ps_refine_prms->u1_max_2nx2n_tu_recur_cands =
ps_me_coding_tools->u1_max_2nx2n_tu_recur_cands;
ps_refine_prms->u1_max_num_fpel_refine_centers =
ps_me_coding_tools->u1_max_num_fpel_refine_centers;
ps_refine_prms->u1_max_num_subpel_refine_centers =
ps_me_coding_tools->u1_max_num_subpel_refine_centers;
}
if(layer_id != 0)
{
ps_refine_prms->i4_num_mvbank_results = ps_refine_prms->i4_num_results_per_part;
}
/* 4 * lambda */
ps_refine_prms->sdi_threshold =
(ps_refine_prms->lambda_recon + (1 << (ps_frm_prms->lambda_q_shift - 1))) >>
(ps_frm_prms->lambda_q_shift - 2);
ps_refine_prms->u1_use_lambda_derived_from_min_8x8_act_in_ctb =
MODULATE_LAMDA_WHEN_SPATIAL_MOD_ON && ps_frm_prms->u1_is_cu_qp_delta_enabled;
}
void hme_set_ctb_boundary_attrs(ctb_boundary_attrs_t *ps_attrs, S32 num_8x8_horz, S32 num_8x8_vert)
{
S32 cu_16x16_valid_flag = 0, merge_pattern_x, merge_pattern_y;
S32 blk, blk_x, blk_y;
S32 num_16x16_horz, num_16x16_vert;
blk_ctb_attrs_t *ps_blk_attrs = &ps_attrs->as_blk_attrs[0];
num_16x16_horz = (num_8x8_horz + 1) >> 1;
num_16x16_vert = (num_8x8_vert + 1) >> 1;
ps_attrs->u1_num_blks_in_ctb = (U08)(num_16x16_horz * num_16x16_vert);
/*************************************************************************/
/* Run through each blk assuming all 16x16 CUs valid. The order would be */
/* 0 1 4 5 */
/* 2 3 6 7 */
/* 8 9 12 13 */
/* 10 11 14 15 */
/* Out of these some may not be valid. For example, if num_16x16_horz is */
/* 2 and num_16x16_vert is 4, then right 2 columns not valid. In this */
/* case, blks 8-11 get encoding number of 4-7. Further, the variable */
/* cu_16x16_valid_flag will be 1111 0000 1111 0000. Also, the variable */
/* u1_merge_to_32x32_flag will be 1010, and u1_merge_to_64x64_flag 0 */
/*************************************************************************/
for(blk = 0; blk < 16; blk++)
{
U08 u1_blk_8x8_mask = 0xF;
blk_x = gau1_encode_to_raster_x[blk];
blk_y = gau1_encode_to_raster_y[blk];
if((blk_x >= num_16x16_horz) || (blk_y >= num_16x16_vert))
{
continue;
}
/* The CU at encode location blk is valid */
cu_16x16_valid_flag |= (1 << blk);
ps_blk_attrs->u1_blk_id_in_full_ctb = blk;
ps_blk_attrs->u1_blk_x = blk_x;
ps_blk_attrs->u1_blk_y = blk_y;
/* Disable blks 1 and 3 if the 16x16 blk overshoots on rt border */
if(((blk_x << 1) + 2) > num_8x8_horz)
u1_blk_8x8_mask &= 0x5;
/* Disable blks 2 and 3 if the 16x16 blk overshoots on bot border */
if(((blk_y << 1) + 2) > num_8x8_vert)
u1_blk_8x8_mask &= 0x3;
ps_blk_attrs->u1_blk_8x8_mask = u1_blk_8x8_mask;
ps_blk_attrs++;
}
ps_attrs->cu_16x16_valid_flag = cu_16x16_valid_flag;
/* 32x32 merge is logical combination of what merge is possible */
/* horizontally as well as vertically. */
if(num_8x8_horz < 4)
merge_pattern_x = 0x0;
else if(num_8x8_horz < 8)
merge_pattern_x = 0x5;
else
merge_pattern_x = 0xF;
if(num_8x8_vert < 4)
merge_pattern_y = 0x0;
else if(num_8x8_vert < 8)
merge_pattern_y = 0x3;
else
merge_pattern_y = 0xF;
ps_attrs->u1_merge_to_32x32_flag = (U08)(merge_pattern_x & merge_pattern_y);
/* Do not attempt 64x64 merge if any blk invalid */
if(ps_attrs->u1_merge_to_32x32_flag != 0xF)
ps_attrs->u1_merge_to_64x64_flag = 0;
else
ps_attrs->u1_merge_to_64x64_flag = 1;
}
void hme_set_ctb_attrs(ctb_boundary_attrs_t *ps_attrs, S32 wd, S32 ht)
{
S32 is_cropped_rt, is_cropped_bot;
is_cropped_rt = ((wd & 63) != 0) ? 1 : 0;
is_cropped_bot = ((ht & 63) != 0) ? 1 : 0;
if(is_cropped_rt)
{
hme_set_ctb_boundary_attrs(&ps_attrs[CTB_RT_PIC_BOUNDARY], (wd & 63) >> 3, 8);
}
if(is_cropped_bot)
{
hme_set_ctb_boundary_attrs(&ps_attrs[CTB_BOT_PIC_BOUNDARY], 8, (ht & 63) >> 3);
}
if(is_cropped_rt & is_cropped_bot)
{
hme_set_ctb_boundary_attrs(
&ps_attrs[CTB_BOT_RT_PIC_BOUNDARY], (wd & 63) >> 3, (ht & 63) >> 3);
}
hme_set_ctb_boundary_attrs(&ps_attrs[CTB_CENTRE], 8, 8);
}
/**
********************************************************************************
* @fn hme_scale_for_ref_idx(S32 curr_poc, S32 poc_from, S32 poc_to)
*
* @brief When we have an mv with ref id "poc_to" for which predictor to be
* computed, and predictor is ref id "poc_from", this funciton returns
* scale factor in Q8 for such a purpose
*
* @param[in] curr_poc : input picture poc
*
* @param[in] poc_from : POC of the pic, pointed to by ref id to be scaled
*
* @param[in] poc_to : POC of hte pic, pointed to by ref id to be scaled to
*
* @return Scale factor in Q8 format
********************************************************************************
*/
S16 hme_scale_for_ref_idx(S32 curr_poc, S32 poc_from, S32 poc_to)
{
S32 td, tx, tb;
S16 i2_scf;
/*************************************************************************/
/* Approximate scale factor: 256 * num / denom */
/* num = curr_poc - poc_to, denom = curr_poc - poc_from */
/* Exact implementation as per standard. */
/*************************************************************************/
tb = HME_CLIP((curr_poc - poc_to), -128, 127);
td = HME_CLIP((curr_poc - poc_from), -128, 127);
tx = (16384 + (ABS(td) >> 1)) / td;
//i2_scf = HME_CLIP((((tb*tx)+32)>>6), -128, 127);
i2_scf = HME_CLIP((((tb * tx) + 32) >> 6), -4096, 4095);
return (i2_scf);
}
/**
********************************************************************************
* @fn hme_process_frm_init
*
* @brief HME frame level initialsation processing function
*
* @param[in] pv_me_ctxt : ME ctxt pointer
*
* @param[in] ps_ref_map : Reference map prms pointer
*
* @param[in] ps_frm_prms :Pointer to frame params
*
* called only for encode layer
*
* @return Scale factor in Q8 format
********************************************************************************
*/
void hme_process_frm_init(
void *pv_me_ctxt,
hme_ref_map_t *ps_ref_map,
hme_frm_prms_t *ps_frm_prms,
WORD32 i4_me_frm_id,
WORD32 i4_num_me_frm_pllel)
{
me_ctxt_t *ps_thrd_ctxt = (me_ctxt_t *)pv_me_ctxt;
me_frm_ctxt_t *ps_ctxt = (me_frm_ctxt_t *)ps_thrd_ctxt->aps_me_frm_prms[i4_me_frm_id];
S32 i, j, desc_idx;
S16 i2_max_x = 0, i2_max_y = 0;
/* Set the Qp of current frm passed by caller. Required for intra cost */
ps_ctxt->frm_qstep = ps_frm_prms->qstep;
ps_ctxt->qstep_ls8 = ps_frm_prms->qstep_ls8;
/* Bidir enabled or not */
ps_ctxt->s_frm_prms = *ps_frm_prms;
/*************************************************************************/
/* Set up the ref pic parameters across all layers. For this, we do the */
/* following: the application has given us a ref pic list, we go index */
/* by index and pick up the picture. A picture can be uniquely be mapped */
/* to a POC. So we search all layer descriptor array to find the POC */
/* Once found, we update all attributes in this descriptor. */
/* During this updation process we also create an index of descriptor id */
/* to ref id mapping. It is important to find the same POC in the layers */
/* descr strcture since it holds the pyramid inputs for non encode layers*/
/* Apart from this, e also update array containing the index of the descr*/
/* During processing for ease of access, each layer has a pointer to aray*/
/* of pointers containing fxfy, fxhy, hxfy, hxhy and inputs for each ref */
/* we update this too. */
/*************************************************************************/
ps_ctxt->num_ref_past = 0;
ps_ctxt->num_ref_future = 0;
for(i = 0; i < ps_ref_map->i4_num_ref; i++)
{
S32 ref_id_lc, idx;
hme_ref_desc_t *ps_ref_desc;
ps_ref_desc = &ps_ref_map->as_ref_desc[i];
ref_id_lc = ps_ref_desc->i1_ref_id_lc;
/* Obtain the id of descriptor that contains this POC */
idx = hme_find_descr_idx(
ps_thrd_ctxt, ps_ref_desc->i4_poc, ps_ref_desc->i4_GOP_num, i4_num_me_frm_pllel);
/* Update all layers in this descr with the reference attributes */
hme_update_layer_desc(
&ps_thrd_ctxt->as_ref_descr[idx],
ps_ref_desc,
0,
1, //ps_ctxt->num_layers,
ps_ctxt->ps_curr_descr);
/* Update the pointer holder for the recon planes */
ps_ctxt->ps_curr_descr->aps_layers[0]->ppu1_list_inp = &ps_ctxt->apu1_list_inp[0][0];
ps_ctxt->ps_curr_descr->aps_layers[0]->ppu1_list_rec_fxfy =
&ps_ctxt->apu1_list_rec_fxfy[0][0];
ps_ctxt->ps_curr_descr->aps_layers[0]->ppu1_list_rec_hxfy =
&ps_ctxt->apu1_list_rec_hxfy[0][0];
ps_ctxt->ps_curr_descr->aps_layers[0]->ppu1_list_rec_fxhy =
&ps_ctxt->apu1_list_rec_fxhy[0][0];
ps_ctxt->ps_curr_descr->aps_layers[0]->ppu1_list_rec_hxhy =
&ps_ctxt->apu1_list_rec_hxhy[0][0];
ps_ctxt->ps_curr_descr->aps_layers[0]->ppv_dep_mngr_recon =
&ps_ctxt->apv_list_dep_mngr[0][0];
/* Update the array having ref id lc to descr id mapping */
ps_ctxt->a_ref_to_descr_id[ps_ref_desc->i1_ref_id_lc] = idx;
/* From ref id lc we need to work out the POC, So update this array */
ps_ctxt->ai4_ref_idx_to_poc_lc[ref_id_lc] = ps_ref_desc->i4_poc;
/* When computing costs in L0 and L1 directions, we need the */
/* respective ref id L0 and L1, so update this mapping */
ps_ctxt->a_ref_idx_lc_to_l0[ref_id_lc] = ps_ref_desc->i1_ref_id_l0;
ps_ctxt->a_ref_idx_lc_to_l1[ref_id_lc] = ps_ref_desc->i1_ref_id_l1;
if((ps_ctxt->i4_curr_poc > ps_ref_desc->i4_poc) || ps_ctxt->i4_curr_poc == 0)
{
ps_ctxt->au1_is_past[ref_id_lc] = 1;
ps_ctxt->ai1_past_list[ps_ctxt->num_ref_past] = ref_id_lc;
ps_ctxt->num_ref_past++;
}
else
{
ps_ctxt->au1_is_past[ref_id_lc] = 0;
ps_ctxt->ai1_future_list[ps_ctxt->num_ref_future] = ref_id_lc;
ps_ctxt->num_ref_future++;
}
if(1 == ps_ctxt->i4_wt_pred_enable_flag)
{
/* copy the weight and offsets from current ref desc */
ps_ctxt->s_wt_pred.a_wpred_wt[ref_id_lc] = ps_ref_desc->i2_weight;
/* inv weight is stored in Q15 format */
ps_ctxt->s_wt_pred.a_inv_wpred_wt[ref_id_lc] =
((1 << 15) + (ps_ref_desc->i2_weight >> 1)) / ps_ref_desc->i2_weight;
ps_ctxt->s_wt_pred.a_wpred_off[ref_id_lc] = ps_ref_desc->i2_offset;
}
else
{
/* store default wt and offset*/
ps_ctxt->s_wt_pred.a_wpred_wt[ref_id_lc] = WGHT_DEFAULT;
/* inv weight is stored in Q15 format */
ps_ctxt->s_wt_pred.a_inv_wpred_wt[ref_id_lc] =
((1 << 15) + (WGHT_DEFAULT >> 1)) / WGHT_DEFAULT;
ps_ctxt->s_wt_pred.a_wpred_off[ref_id_lc] = 0;
}
}
ps_ctxt->ai1_future_list[ps_ctxt->num_ref_future] = -1;
ps_ctxt->ai1_past_list[ps_ctxt->num_ref_past] = -1;
/*************************************************************************/
/* Preparation of the TLU for bits for reference indices. */
/* Special case is that of numref = 2. (TEV) */
/* Other cases uses UEV */
/*************************************************************************/
for(i = 0; i < MAX_NUM_REF; i++)
{
ps_ctxt->au1_ref_bits_tlu_lc[0][i] = 0;
ps_ctxt->au1_ref_bits_tlu_lc[1][i] = 0;
}
if(ps_ref_map->i4_num_ref == 2)
{
ps_ctxt->au1_ref_bits_tlu_lc[0][0] = 1;
ps_ctxt->au1_ref_bits_tlu_lc[1][0] = 1;
ps_ctxt->au1_ref_bits_tlu_lc[0][1] = 1;
ps_ctxt->au1_ref_bits_tlu_lc[1][1] = 1;
}
else if(ps_ref_map->i4_num_ref > 2)
{
for(i = 0; i < ps_ref_map->i4_num_ref; i++)
{
S32 l0, l1;
l0 = ps_ctxt->a_ref_idx_lc_to_l0[i];
l1 = ps_ctxt->a_ref_idx_lc_to_l1[i];
ps_ctxt->au1_ref_bits_tlu_lc[0][i] = gau1_ref_bits[l0];
ps_ctxt->au1_ref_bits_tlu_lc[1][i] = gau1_ref_bits[l1];
}
}
/*************************************************************************/
/* Preparation of the scaling factors for reference indices. The scale */
/* factor depends on distance of the two ref indices from current input */
/* in terms of poc delta. */
/*************************************************************************/
for(i = 0; i < ps_ref_map->i4_num_ref; i++)
{
for(j = 0; j < ps_ref_map->i4_num_ref; j++)
{
S16 i2_scf_q8;
S32 poc_from, poc_to;
poc_from = ps_ctxt->ai4_ref_idx_to_poc_lc[j];
poc_to = ps_ctxt->ai4_ref_idx_to_poc_lc[i];
i2_scf_q8 = hme_scale_for_ref_idx(ps_ctxt->i4_curr_poc, poc_from, poc_to);
ps_ctxt->ai2_ref_scf[j + i * MAX_NUM_REF] = i2_scf_q8;
}
}
/*************************************************************************/
/* We store simplified look ups for 4 hpel planes and inp y plane for */
/* every layer and for every ref id in the layer. So update these lookups*/
/*************************************************************************/
for(i = 0; i < 1; i++)
{
U08 **ppu1_rec_fxfy, **ppu1_rec_hxfy, **ppu1_rec_fxhy, **ppu1_rec_hxhy;
U08 **ppu1_inp;
void **ppvlist_dep_mngr;
layer_ctxt_t *ps_layer_ctxt = ps_ctxt->ps_curr_descr->aps_layers[i];
ppvlist_dep_mngr = &ps_ctxt->apv_list_dep_mngr[i][0];
ppu1_rec_fxfy = &ps_ctxt->apu1_list_rec_fxfy[i][0];
ppu1_rec_hxfy = &ps_ctxt->apu1_list_rec_hxfy[i][0];
ppu1_rec_fxhy = &ps_ctxt->apu1_list_rec_fxhy[i][0];
ppu1_rec_hxhy = &ps_ctxt->apu1_list_rec_hxhy[i][0];
ppu1_inp = &ps_ctxt->apu1_list_inp[i][0];
for(j = 0; j < ps_ref_map->i4_num_ref; j++)
{
hme_ref_desc_t *ps_ref_desc;
hme_ref_buf_info_t *ps_buf_info;
layer_ctxt_t *ps_layer;
S32 ref_id_lc;
ps_ref_desc = &ps_ref_map->as_ref_desc[j];
ps_buf_info = &ps_ref_desc->as_ref_info[i];
ref_id_lc = ps_ref_desc->i1_ref_id_lc;
desc_idx = ps_ctxt->a_ref_to_descr_id[ref_id_lc];
ps_layer = ps_thrd_ctxt->as_ref_descr[desc_idx].aps_layers[i];
ppu1_inp[j] = ps_buf_info->pu1_ref_src;
ppu1_rec_fxfy[j] = ps_buf_info->pu1_rec_fxfy;
ppu1_rec_hxfy[j] = ps_buf_info->pu1_rec_hxfy;
ppu1_rec_fxhy[j] = ps_buf_info->pu1_rec_fxhy;
ppu1_rec_hxhy[j] = ps_buf_info->pu1_rec_hxhy;
ppvlist_dep_mngr[j] = ps_buf_info->pv_dep_mngr;
/* Update the curr descriptors reference pointers here */
ps_layer_ctxt->ppu1_list_inp[j] = ps_buf_info->pu1_ref_src;
ps_layer_ctxt->ppu1_list_rec_fxfy[j] = ps_buf_info->pu1_rec_fxfy;
ps_layer_ctxt->ppu1_list_rec_hxfy[j] = ps_buf_info->pu1_rec_hxfy;
ps_layer_ctxt->ppu1_list_rec_fxhy[j] = ps_buf_info->pu1_rec_fxhy;
ps_layer_ctxt->ppu1_list_rec_hxhy[j] = ps_buf_info->pu1_rec_hxhy;
}
}
/*************************************************************************/
/* The mv range for each layer is computed. For dyadic layers it will */
/* keep shrinking by 2, for non dyadic it will shrink by ratio of wd and */
/* ht. In general formula used is scale by ratio of wd for x and ht for y*/
/*************************************************************************/
for(i = 0; i < 1; i++)
{
layer_ctxt_t *ps_layer_ctxt;
if(i == 0)
{
i2_max_x = ps_frm_prms->i2_mv_range_x;
i2_max_y = ps_frm_prms->i2_mv_range_y;
}
else
{
i2_max_x = (S16)FLOOR8(((i2_max_x * ps_ctxt->i4_wd) / ps_ctxt->i4_wd));
i2_max_y = (S16)FLOOR8(((i2_max_y * ps_ctxt->i4_ht) / ps_ctxt->i4_ht));
}
ps_layer_ctxt = ps_ctxt->ps_curr_descr->aps_layers[i];
ps_layer_ctxt->i2_max_mv_x = i2_max_x;
ps_layer_ctxt->i2_max_mv_y = i2_max_y;
/*********************************************************************/
/* Every layer maintains a reference id lc to POC mapping. This is */
/* because the mapping is unique for every frm. Also, in next frm, */
/* we require colocated mvs which means scaling according to temporal*/
/*distance. Hence this mapping needs to be maintained in every */
/* layer ctxt */
/*********************************************************************/
memset(ps_layer_ctxt->ai4_ref_id_to_poc_lc, -1, sizeof(S32) * ps_ctxt->max_num_ref);
if(ps_ref_map->i4_num_ref)
{
memcpy(
ps_layer_ctxt->ai4_ref_id_to_poc_lc,
ps_ctxt->ai4_ref_idx_to_poc_lc,
ps_ref_map->i4_num_ref * sizeof(S32));
}
}
return;
}
/**
********************************************************************************
* @fn hme_coarse_process_frm_init
*
* @brief HME frame level initialsation processing function
*
* @param[in] pv_me_ctxt : ME ctxt pointer
*
* @param[in] ps_ref_map : Reference map prms pointer
*
* @param[in] ps_frm_prms :Pointer to frame params
*
* @return Scale factor in Q8 format
********************************************************************************
*/
void hme_coarse_process_frm_init(
void *pv_me_ctxt, hme_ref_map_t *ps_ref_map, hme_frm_prms_t *ps_frm_prms)
{
coarse_me_ctxt_t *ps_ctxt = (coarse_me_ctxt_t *)pv_me_ctxt;
S32 i, j, desc_idx;
S16 i2_max_x = 0, i2_max_y = 0;
/* Set the Qp of current frm passed by caller. Required for intra cost */
ps_ctxt->frm_qstep = ps_frm_prms->qstep;
/* Bidir enabled or not */
ps_ctxt->s_frm_prms = *ps_frm_prms;
/*************************************************************************/
/* Set up the ref pic parameters across all layers. For this, we do the */
/* following: the application has given us a ref pic list, we go index */
/* by index and pick up the picture. A picture can be uniquely be mapped */
/* to a POC. So we search all layer descriptor array to find the POC */
/* Once found, we update all attributes in this descriptor. */
/* During this updation process we also create an index of descriptor id */
/* to ref id mapping. It is important to find the same POC in the layers */
/* descr strcture since it holds the pyramid inputs for non encode layers*/
/* Apart from this, e also update array containing the index of the descr*/
/* During processing for ease of access, each layer has a pointer to aray*/
/* of pointers containing fxfy, fxhy, hxfy, hxhy and inputs for each ref */
/* we update this too. */
/*************************************************************************/
ps_ctxt->num_ref_past = 0;
ps_ctxt->num_ref_future = 0;
for(i = 0; i < ps_ref_map->i4_num_ref; i++)
{
S32 ref_id_lc, idx;
hme_ref_desc_t *ps_ref_desc;
ps_ref_desc = &ps_ref_map->as_ref_desc[i];
ref_id_lc = ps_ref_desc->i1_ref_id_lc;
/* Obtain the id of descriptor that contains this POC */
idx = hme_coarse_find_descr_idx(ps_ctxt, ps_ref_desc->i4_poc);
/* Update all layers in this descr with the reference attributes */
hme_update_layer_desc(
&ps_ctxt->as_ref_descr[idx],
ps_ref_desc,
1,
ps_ctxt->num_layers - 1,
ps_ctxt->ps_curr_descr);
/* Update the array having ref id lc to descr id mapping */
ps_ctxt->a_ref_to_descr_id[ps_ref_desc->i1_ref_id_lc] = idx;
/* From ref id lc we need to work out the POC, So update this array */
ps_ctxt->ai4_ref_idx_to_poc_lc[ref_id_lc] = ps_ref_desc->i4_poc;
/* From ref id lc we need to work out the display num, So update this array */
ps_ctxt->ai4_ref_idx_to_disp_num[ref_id_lc] = ps_ref_desc->i4_display_num;
/* When computing costs in L0 and L1 directions, we need the */
/* respective ref id L0 and L1, so update this mapping */
ps_ctxt->a_ref_idx_lc_to_l0[ref_id_lc] = ps_ref_desc->i1_ref_id_l0;
ps_ctxt->a_ref_idx_lc_to_l1[ref_id_lc] = ps_ref_desc->i1_ref_id_l1;
if((ps_ctxt->i4_curr_poc > ps_ref_desc->i4_poc) || ps_ctxt->i4_curr_poc == 0)
{
ps_ctxt->au1_is_past[ref_id_lc] = 1;
ps_ctxt->ai1_past_list[ps_ctxt->num_ref_past] = ref_id_lc;
ps_ctxt->num_ref_past++;
}
else
{
ps_ctxt->au1_is_past[ref_id_lc] = 0;
ps_ctxt->ai1_future_list[ps_ctxt->num_ref_future] = ref_id_lc;
ps_ctxt->num_ref_future++;
}
if(1 == ps_ctxt->i4_wt_pred_enable_flag)
{
/* copy the weight and offsets from current ref desc */
ps_ctxt->s_wt_pred.a_wpred_wt[ref_id_lc] = ps_ref_desc->i2_weight;
/* inv weight is stored in Q15 format */
ps_ctxt->s_wt_pred.a_inv_wpred_wt[ref_id_lc] =
((1 << 15) + (ps_ref_desc->i2_weight >> 1)) / ps_ref_desc->i2_weight;
ps_ctxt->s_wt_pred.a_wpred_off[ref_id_lc] = ps_ref_desc->i2_offset;
}
else
{
/* store default wt and offset*/
ps_ctxt->s_wt_pred.a_wpred_wt[ref_id_lc] = WGHT_DEFAULT;
/* inv weight is stored in Q15 format */
ps_ctxt->s_wt_pred.a_inv_wpred_wt[ref_id_lc] =
((1 << 15) + (WGHT_DEFAULT >> 1)) / WGHT_DEFAULT;
ps_ctxt->s_wt_pred.a_wpred_off[ref_id_lc] = 0;
}
}
ps_ctxt->ai1_future_list[ps_ctxt->num_ref_future] = -1;
ps_ctxt->ai1_past_list[ps_ctxt->num_ref_past] = -1;
/*************************************************************************/
/* Preparation of the TLU for bits for reference indices. */
/* Special case is that of numref = 2. (TEV) */
/* Other cases uses UEV */
/*************************************************************************/
for(i = 0; i < MAX_NUM_REF; i++)
{
ps_ctxt->au1_ref_bits_tlu_lc[0][i] = 0;
ps_ctxt->au1_ref_bits_tlu_lc[1][i] = 0;
}
if(ps_ref_map->i4_num_ref == 2)
{
ps_ctxt->au1_ref_bits_tlu_lc[0][0] = 1;
ps_ctxt->au1_ref_bits_tlu_lc[1][0] = 1;
ps_ctxt->au1_ref_bits_tlu_lc[0][1] = 1;
ps_ctxt->au1_ref_bits_tlu_lc[1][1] = 1;
}
else if(ps_ref_map->i4_num_ref > 2)
{
for(i = 0; i < ps_ref_map->i4_num_ref; i++)
{
S32 l0, l1;
l0 = ps_ctxt->a_ref_idx_lc_to_l0[i];
l1 = ps_ctxt->a_ref_idx_lc_to_l1[i];
ps_ctxt->au1_ref_bits_tlu_lc[0][i] = gau1_ref_bits[l0];
ps_ctxt->au1_ref_bits_tlu_lc[1][i] = gau1_ref_bits[l1];
}
}
/*************************************************************************/
/* Preparation of the scaling factors for reference indices. The scale */
/* factor depends on distance of the two ref indices from current input */
/* in terms of poc delta. */
/*************************************************************************/
for(i = 0; i < ps_ref_map->i4_num_ref; i++)
{
for(j = 0; j < ps_ref_map->i4_num_ref; j++)
{
S16 i2_scf_q8;
S32 poc_from, poc_to;
poc_from = ps_ctxt->ai4_ref_idx_to_poc_lc[j];
poc_to = ps_ctxt->ai4_ref_idx_to_poc_lc[i];
i2_scf_q8 = hme_scale_for_ref_idx(ps_ctxt->i4_curr_poc, poc_from, poc_to);
ps_ctxt->ai2_ref_scf[j + i * MAX_NUM_REF] = i2_scf_q8;
}
}
/*************************************************************************/
/* We store simplified look ups for inp y plane for */
/* every layer and for every ref id in the layer. */
/*************************************************************************/
for(i = 1; i < ps_ctxt->num_layers; i++)
{
U08 **ppu1_inp;
ppu1_inp = &ps_ctxt->apu1_list_inp[i][0];
for(j = 0; j < ps_ref_map->i4_num_ref; j++)
{
hme_ref_desc_t *ps_ref_desc;
hme_ref_buf_info_t *ps_buf_info;
layer_ctxt_t *ps_layer;
S32 ref_id_lc;
ps_ref_desc = &ps_ref_map->as_ref_desc[j];
ps_buf_info = &ps_ref_desc->as_ref_info[i];
ref_id_lc = ps_ref_desc->i1_ref_id_lc;
desc_idx = ps_ctxt->a_ref_to_descr_id[ref_id_lc];
ps_layer = ps_ctxt->as_ref_descr[desc_idx].aps_layers[i];
ppu1_inp[j] = ps_layer->pu1_inp;
}
}
/*************************************************************************/
/* The mv range for each layer is computed. For dyadic layers it will */
/* keep shrinking by 2, for non dyadic it will shrink by ratio of wd and */
/* ht. In general formula used is scale by ratio of wd for x and ht for y*/
/*************************************************************************/
/* set to layer 0 search range params */
i2_max_x = ps_frm_prms->i2_mv_range_x;
i2_max_y = ps_frm_prms->i2_mv_range_y;
for(i = 1; i < ps_ctxt->num_layers; i++)
{
layer_ctxt_t *ps_layer_ctxt;
{
i2_max_x = (S16)FLOOR8(((i2_max_x * ps_ctxt->a_wd[i]) / ps_ctxt->a_wd[i - 1]));
i2_max_y = (S16)FLOOR8(((i2_max_y * ps_ctxt->a_ht[i]) / ps_ctxt->a_ht[i - 1]));
}
ps_layer_ctxt = ps_ctxt->ps_curr_descr->aps_layers[i];
ps_layer_ctxt->i2_max_mv_x = i2_max_x;
ps_layer_ctxt->i2_max_mv_y = i2_max_y;
/*********************************************************************/
/* Every layer maintains a reference id lc to POC mapping. This is */
/* because the mapping is unique for every frm. Also, in next frm, */
/* we require colocated mvs which means scaling according to temporal*/
/*distance. Hence this mapping needs to be maintained in every */
/* layer ctxt */
/*********************************************************************/
memset(ps_layer_ctxt->ai4_ref_id_to_poc_lc, -1, sizeof(S32) * ps_ctxt->max_num_ref);
if(ps_ref_map->i4_num_ref)
{
memcpy(
ps_layer_ctxt->ai4_ref_id_to_poc_lc,
ps_ctxt->ai4_ref_idx_to_poc_lc,
ps_ref_map->i4_num_ref * sizeof(S32));
memcpy(
ps_layer_ctxt->ai4_ref_id_to_disp_num,
ps_ctxt->ai4_ref_idx_to_disp_num,
ps_ref_map->i4_num_ref * sizeof(S32));
}
}
return;
}
/**
********************************************************************************
* @fn hme_process_frm
*
* @brief HME frame level processing function
*
* @param[in] pv_me_ctxt : ME ctxt pointer
*
* @param[in] ps_ref_map : Reference map prms pointer
*
* @param[in] ppd_intra_costs : pointer to array of intra cost cost buffers for each layer
*
* @param[in] ps_frm_prms : pointer to Frame level parameters of HME
*
* @param[in] pf_ext_update_fxn : function pointer to update CTb results
*
* @param[in] pf_get_intra_cu_and_cost :function pointer to get intra cu size and cost
*
* @param[in] ps_multi_thrd_ctxt :function pointer to get intra cu size and cost
*
* @return Scale factor in Q8 format
********************************************************************************
*/
void hme_process_frm(
void *pv_me_ctxt,
pre_enc_L0_ipe_encloop_ctxt_t *ps_l0_ipe_input,
hme_ref_map_t *ps_ref_map,
double **ppd_intra_costs,
hme_frm_prms_t *ps_frm_prms,
PF_EXT_UPDATE_FXN_T pf_ext_update_fxn,
void *pv_coarse_layer,
void *pv_multi_thrd_ctxt,
S32 i4_frame_parallelism_level,
S32 thrd_id,
S32 i4_me_frm_id)
{
refine_prms_t s_refine_prms;
me_ctxt_t *ps_thrd_ctxt = (me_ctxt_t *)pv_me_ctxt;
me_frm_ctxt_t *ps_ctxt = ps_thrd_ctxt->aps_me_frm_prms[i4_me_frm_id];
S32 lyr_job_type;
multi_thrd_ctxt_t *ps_multi_thrd_ctxt;
layer_ctxt_t *ps_coarse_layer = (layer_ctxt_t *)pv_coarse_layer;
ps_multi_thrd_ctxt = (multi_thrd_ctxt_t *)pv_multi_thrd_ctxt;
lyr_job_type = ME_JOB_ENC_LYR;
/*************************************************************************/
/* Final L0 layer ME call */
/*************************************************************************/
{
/* Set the CTB attributes dependin on corner/rt edge/bot edge/center*/
hme_set_ctb_attrs(ps_ctxt->as_ctb_bound_attrs, ps_ctxt->i4_wd, ps_ctxt->i4_ht);
hme_set_refine_prms(
&s_refine_prms,
ps_ctxt->u1_encode[0],
ps_ref_map->i4_num_ref,
0,
ps_ctxt->num_layers,
ps_ctxt->num_layers_explicit_search,
ps_thrd_ctxt->s_init_prms.use_4x4,
ps_frm_prms,
ppd_intra_costs,
&ps_thrd_ctxt->s_init_prms.s_me_coding_tools);
hme_refine(
ps_thrd_ctxt,
&s_refine_prms,
pf_ext_update_fxn,
ps_coarse_layer,
ps_multi_thrd_ctxt,
lyr_job_type,
thrd_id,
i4_me_frm_id,
ps_l0_ipe_input);
/* Set current ref pic status which will used as perv frame ref pic */
if(i4_frame_parallelism_level)
{
ps_ctxt->i4_is_prev_frame_reference = 0;
}
else
{
ps_ctxt->i4_is_prev_frame_reference =
ps_multi_thrd_ctxt->aps_cur_inp_me_prms[i4_me_frm_id]
->ps_curr_inp->s_lap_out.i4_is_ref_pic;
}
}
return;
}
/**
********************************************************************************
* @fn hme_coarse_process_frm
*
* @brief HME frame level processing function (coarse + refine)
*
* @param[in] pv_me_ctxt : ME ctxt pointer
*
* @param[in] ps_ref_map : Reference map prms pointer
*
* @param[in] ps_frm_prms : pointer to Frame level parameters of HME
*
* @param[in] ps_multi_thrd_ctxt :Multi thread related ctxt
*
* @return Scale factor in Q8 format
********************************************************************************
*/
void hme_coarse_process_frm(
void *pv_me_ctxt,
hme_ref_map_t *ps_ref_map,
hme_frm_prms_t *ps_frm_prms,
void *pv_multi_thrd_ctxt,
WORD32 i4_ping_pong,
void **ppv_dep_mngr_hme_sync)
{
S16 i2_max;
S32 layer_id;
coarse_prms_t s_coarse_prms;
refine_prms_t s_refine_prms;
coarse_me_ctxt_t *ps_ctxt = (coarse_me_ctxt_t *)pv_me_ctxt;
S32 lyr_job_type;
multi_thrd_ctxt_t *ps_multi_thrd_ctxt;
ps_multi_thrd_ctxt = (multi_thrd_ctxt_t *)pv_multi_thrd_ctxt;
/*************************************************************************/
/* Fire processing of all layers, starting with coarsest layer. */
/*************************************************************************/
layer_id = ps_ctxt->num_layers - 1;
i2_max = ps_ctxt->ps_curr_descr->aps_layers[layer_id]->i2_max_mv_x;
i2_max = MAX(i2_max, ps_ctxt->ps_curr_descr->aps_layers[layer_id]->i2_max_mv_y);
s_coarse_prms.i4_layer_id = layer_id;
{
S32 log_start_step;
/* Based on Preset, set the starting step size for Refinement */
if(ME_MEDIUM_SPEED > ps_ctxt->s_init_prms.s_me_coding_tools.e_me_quality_presets)
{
log_start_step = 0;
}
else
{
log_start_step = 1;
}
s_coarse_prms.i4_max_iters = i2_max >> log_start_step;
s_coarse_prms.i4_start_step = 1 << log_start_step;
}
s_coarse_prms.i4_num_ref = ps_ref_map->i4_num_ref;
s_coarse_prms.do_full_search = 1;
if(s_coarse_prms.do_full_search)
{
/* Set to 2 or 4 */
if(ps_ctxt->s_init_prms.s_me_coding_tools.e_me_quality_presets < ME_MEDIUM_SPEED)
s_coarse_prms.full_search_step = HME_COARSE_STEP_SIZE_HIGH_QUALITY;
else if(ps_ctxt->s_init_prms.s_me_coding_tools.e_me_quality_presets >= ME_MEDIUM_SPEED)
s_coarse_prms.full_search_step = HME_COARSE_STEP_SIZE_HIGH_SPEED;
}
s_coarse_prms.num_results = ps_ctxt->max_num_results_coarse;
/* Coarse layer uses only 1 lambda, i.e. the one for open loop ME */
s_coarse_prms.lambda = ps_frm_prms->i4_ol_sad_lambda_qf;
s_coarse_prms.lambda_q_shift = ps_frm_prms->lambda_q_shift;
s_coarse_prms.lambda = ((float)s_coarse_prms.lambda * (100.0 - ME_LAMBDA_DISCOUNT) / 100.0);
hme_coarsest(ps_ctxt, &s_coarse_prms, ps_multi_thrd_ctxt, i4_ping_pong, ppv_dep_mngr_hme_sync);
/* all refinement layer processed in the loop below */
layer_id--;
lyr_job_type = ps_multi_thrd_ctxt->i4_me_coarsest_lyr_type + 1;
/*************************************************************************/
/* This loop will run for all refine layers (non- encode layers) */
/*************************************************************************/
while(layer_id > 0)
{
hme_set_refine_prms(
&s_refine_prms,
ps_ctxt->u1_encode[layer_id],
ps_ref_map->i4_num_ref,
layer_id,
ps_ctxt->num_layers,
ps_ctxt->num_layers_explicit_search,
ps_ctxt->s_init_prms.use_4x4,
ps_frm_prms,
NULL,
&ps_ctxt->s_init_prms.s_me_coding_tools);
hme_refine_no_encode(
ps_ctxt,
&s_refine_prms,
ps_multi_thrd_ctxt,
lyr_job_type,
i4_ping_pong,
ppv_dep_mngr_hme_sync);
layer_id--;
lyr_job_type++;
}
}
/**
********************************************************************************
* @fn hme_fill_neighbour_mvs
*
* @brief HME neighbour MV population function
*
* @param[in] pps_mv_grid : MV grid array pointer
*
* @param[in] i4_ctb_x : CTB pos X
* @param[in] i4_ctb_y : CTB pos Y
*
* @remarks : Needs to be populated for proper implementation of cost fxn
*
* @return Scale factor in Q8 format
********************************************************************************
*/
void hme_fill_neighbour_mvs(
mv_grid_t **pps_mv_grid, S32 i4_ctb_x, S32 i4_ctb_y, S32 i4_num_ref, void *pv_ctxt)
{
/* TODO : Needs to be populated for proper implementation of cost fxn */
ARG_NOT_USED(pps_mv_grid);
ARG_NOT_USED(i4_ctb_x);
ARG_NOT_USED(i4_ctb_y);
ARG_NOT_USED(i4_num_ref);
ARG_NOT_USED(pv_ctxt);
}
/**
*******************************************************************************
* @fn void hme_get_active_pocs_list(void *pv_me_ctxt,
* S32 *p_pocs_buffered_in_me)
*
* @brief Returns the list of active POCs in ME ctxt
*
* @param[in] pv_me_ctxt : handle to ME context
*
* @param[out] p_pocs_buffered_in_me : pointer to an array which this fxn
* populates with pocs active
*
* @return void
*******************************************************************************
*/
WORD32 hme_get_active_pocs_list(void *pv_me_ctxt, S32 i4_num_me_frm_pllel)
{
me_ctxt_t *ps_ctxt = (me_ctxt_t *)pv_me_ctxt;
S32 i, count = 0;
for(i = 0; i < (ps_ctxt->aps_me_frm_prms[0]->max_num_ref * i4_num_me_frm_pllel) + 1; i++)
{
S32 poc = ps_ctxt->as_ref_descr[i].aps_layers[0]->i4_poc;
S32 i4_is_free = ps_ctxt->as_ref_descr[i].aps_layers[0]->i4_is_free;
if((i4_is_free == 0) && (poc != INVALID_POC))
{
count++;
}
}
if(count == (ps_ctxt->aps_me_frm_prms[0]->max_num_ref * i4_num_me_frm_pllel) + 1)
{
return 1;
}
else
{
return 0;
}
}
/**
*******************************************************************************
* @fn void hme_coarse_get_active_pocs_list(void *pv_me_ctxt,
* S32 *p_pocs_buffered_in_me)
*
* @brief Returns the list of active POCs in ME ctxt
*
* @param[in] pv_me_ctxt : handle to ME context
*
* @param[out] p_pocs_buffered_in_me : pointer to an array which this fxn
* populates with pocs active
*
* @return void
*******************************************************************************
*/
void hme_coarse_get_active_pocs_list(void *pv_me_ctxt, S32 *p_pocs_buffered_in_me)
{
coarse_me_ctxt_t *ps_ctxt = (coarse_me_ctxt_t *)pv_me_ctxt;
S32 i, count = 0;
for(i = 0; i < ps_ctxt->max_num_ref + 1 + NUM_BUFS_DECOMP_HME; i++)
{
S32 poc = ps_ctxt->as_ref_descr[i].aps_layers[1]->i4_poc;
if(poc != -1)
{
p_pocs_buffered_in_me[count] = poc;
count++;
}
}
p_pocs_buffered_in_me[count] = -1;
}
S32 hme_get_blk_size(S32 use_4x4, S32 layer_id, S32 n_layers, S32 encode)
{
/* coarsest layer uses 4x4 blks, lowermost layer/encode layer uses 16x16 */
if(layer_id == n_layers - 1)
return 4;
else if((layer_id == 0) || (encode))
return 16;
/* Intermediate non encode layers use 8 */
return 8;
}