| /****************************************************************************** |
| * |
| * 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; |
| } |