/****************************************************************************** * * Copyright (C) 2022 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 * isvce_ilp_mv.c * * @brief * Contains functions used for deriving inter_layer MV's * ******************************************************************************* */ #include #include #include #include "ih264_typedefs.h" #include "ih264_debug.h" #include "isvc_macros.h" #include "isvc_defs.h" #include "isvce_defs.h" #include "isvce_structs.h" #include "isvce_ilp_mv_private_defs.h" #include "isvce_ilp_mv.h" #include "isvce_ilp_mv_utils.h" /** ******************************************************************************* * * @brief * Returns size of buffers for storing ILP MV ctxt * * @param[in] u1_num_spatial_layers * Num Spatial Layers * * @param[in] d_spatial_res_ratio * Resolution Ratio b/w spatial layers * * @param[in] u4_wd * Input Width * * @param[in] u4_ht * Input Height * * @returns Size of buffers * ******************************************************************************* */ UWORD32 isvce_get_ilp_mv_ctxt_size(UWORD8 u1_num_spatial_layers, DOUBLE d_spatial_res_ratio, UWORD32 u4_wd, UWORD32 u4_ht) { UWORD32 u4_size = 0; if(u1_num_spatial_layers > 1) { WORD32 i; u4_size += MAX_PROCESS_CTXT * sizeof(svc_ilp_mv_ctxt_t); u4_size += MAX_PROCESS_CTXT * sizeof(ilp_mv_state_t); u4_size += u1_num_spatial_layers * sizeof(ilp_mv_layer_state_t); for(i = u1_num_spatial_layers - 1; i >= 1; i--) { WORD32 i4_layer_luma_wd = (WORD32) ((DOUBLE) u4_wd / pow(d_spatial_res_ratio, u1_num_spatial_layers - 1 - i)) + 0.99; WORD32 i4_layer_luma_ht = ((DOUBLE) u4_ht / pow(d_spatial_res_ratio, u1_num_spatial_layers - 1 - i)) + 0.99; WORD32 i4_layer_luma_mbs = (i4_layer_luma_wd / MB_SIZE) * (i4_layer_luma_ht / MB_SIZE); u4_size += i4_layer_luma_mbs * sizeof(ilp_mv_mb_state_t); } } return u4_size; } static FORCEINLINE void isvce_ref_layer_pu_and_mb_pos_init(layer_resampler_props_t *ps_layer_props, ilp_mv_mb_state_t *ps_mb_state, coordinates_t *ps_mb_pos, UWORD32 u4_ref_wd, UWORD32 u4_ref_ht, UWORD8 u1_field_pic_flag, UWORD8 u1_field_mb_flag) { UWORD32 i, j; coordinates_t(*aps_pu_positions)[MAX_PU_IN_MB_ROW] = ps_mb_state->as_pu_positions; coordinates_t(*aps_mb_positions)[MAX_PU_IN_MB_ROW] = ps_mb_state->as_mb_positions; for(i = 0; i < MAX_PU_IN_MB_COL; i++) { UWORD32 u4_y_ref16; UWORD32 u4_yc = ps_mb_pos->i4_ordinate * ps_layer_props->u4_mb_ht + (4 * i + 1) * (1 + u1_field_mb_flag - u1_field_pic_flag); u4_y_ref16 = (u4_yc * ps_layer_props->u4_scale_y + (1 << (ps_layer_props->u4_shift_y - 1))) >> ps_layer_props->u4_shift_y; u4_y_ref16 = MIN(u4_y_ref16, u4_ref_ht - 1); for(j = 0; j < MAX_PU_IN_MB_ROW; j++) { UWORD32 u4_x_ref16; UWORD32 u4_xc = ps_mb_pos->i4_abscissa * ps_layer_props->u4_mb_wd + 4 * j + 1; u4_x_ref16 = (u4_xc * ps_layer_props->u4_scale_x + (1 << (ps_layer_props->u4_shift_x - 1))) >> ps_layer_props->u4_shift_x; u4_x_ref16 = MIN(u4_x_ref16, u4_ref_wd - 1); aps_pu_positions[i][j].i4_abscissa = u4_x_ref16; aps_pu_positions[i][j].i4_ordinate = u4_y_ref16; aps_mb_positions[i][j].i4_abscissa = (u4_x_ref16 / MB_SIZE); aps_mb_positions[i][j].i4_ordinate = (u4_y_ref16 / MB_SIZE); } } } static void isvce_ilp_mv_layer_state_init(ilp_mv_layer_state_t *ps_layer_state, DOUBLE d_spatial_res_ratio, UWORD32 u4_wd, UWORD32 u4_ht) { UWORD32 i, j; const UWORD8 u1_ref_layer_field_pic_flag = 0; const UWORD8 u1_field_pic_flag = 0; const UWORD8 u1_field_mb_flag = 0; ilp_mv_mb_state_t *ps_mb_states; layer_resampler_props_t *ps_layer_props; UWORD32 u4_wd_in_mbs; UWORD32 u4_ht_in_mbs; UWORD32 u4_ref_wd = (u4_wd / d_spatial_res_ratio); UWORD32 u4_ref_ht = (u4_ht / d_spatial_res_ratio) * (1 + u1_ref_layer_field_pic_flag); UWORD32 u4_scaled_wd = u4_wd; UWORD32 u4_scaled_ht = u4_ht * (1 + u1_field_pic_flag); ps_mb_states = ps_layer_state->ps_mb_states; ps_layer_props = ps_layer_state->ps_props; u4_wd_in_mbs = u4_scaled_wd / ps_layer_props->u4_mb_wd; u4_ht_in_mbs = u4_scaled_ht / ps_layer_props->u4_mb_ht; ps_layer_state->s_mv_scale.i4_abscissa = ((u4_scaled_wd << 16) + (u4_ref_wd >> 1)) / u4_ref_wd; ps_layer_state->s_mv_scale.i4_ordinate = ((u4_scaled_ht << 16) + (u4_ref_ht >> 1)) / u4_ref_ht; for(i = 0; i < u4_ht_in_mbs; i++) { for(j = 0; j < u4_wd_in_mbs; j++) { coordinates_t s_mb_pos = {j, i}; isvce_ref_layer_pu_and_mb_pos_init(ps_layer_props, &ps_mb_states[j + i * u4_wd_in_mbs], &s_mb_pos, u4_ref_wd, u4_ref_ht, u1_field_pic_flag, u1_field_mb_flag); } } } /** ******************************************************************************* * * @brief * Function to initialize svc ilp buffers * * @param[in] ps_codec * Pointer to codec context * * @param[in] ps_mem_rec * Pointer to memory allocated for input buffers * ******************************************************************************* */ void isvce_ilp_mv_ctxt_init(isvce_codec_t *ps_codec, iv_mem_rec_t *ps_mem_rec) { WORD32 i, j; const WORD32 i4_num_proc_ctxts = sizeof(ps_codec->as_process) / sizeof(ps_codec->as_process[0]); UWORD8 u1_num_spatial_layers = ps_codec->s_cfg.s_svc_params.u1_num_spatial_layers; if(u1_num_spatial_layers > 1) { ilp_mv_layer_state_t *ps_layer_states = NULL; ilp_mv_mb_state_t *aps_luma_mb_states[MAX_NUM_SPATIAL_LAYERS]; DOUBLE d_spatial_res_ratio = ps_codec->s_cfg.s_svc_params.d_spatial_res_ratio; UWORD32 u4_wd = ps_codec->s_cfg.u4_wd; UWORD32 u4_ht = ps_codec->s_cfg.u4_ht; UWORD8 *pu1_buf = ps_mem_rec->pv_base; WORD64 i8_alloc_mem_size = isvce_get_ilp_mv_ctxt_size(u1_num_spatial_layers, d_spatial_res_ratio, u4_wd, u4_ht); for(i = 0; i < i4_num_proc_ctxts; i++) { ilp_mv_state_t *ps_ilp_mv_state; svc_ilp_mv_ctxt_t *ps_ilp_mv_ctxt; isvce_process_ctxt_t *ps_proc = ps_codec->as_process + i; ps_ilp_mv_ctxt = ps_proc->ps_svc_ilp_mv_ctxt = (svc_ilp_mv_ctxt_t *) pu1_buf; pu1_buf += sizeof(svc_ilp_mv_ctxt_t); i8_alloc_mem_size -= sizeof(svc_ilp_mv_ctxt_t); ps_ilp_mv_ctxt->s_ilp_mv_constants.pv_state = pu1_buf; ps_ilp_mv_state = (ilp_mv_state_t *) pu1_buf; pu1_buf += sizeof(ilp_mv_state_t); i8_alloc_mem_size -= sizeof(ilp_mv_state_t); if(0 == i) { ps_ilp_mv_state->ps_layer_state = (ilp_mv_layer_state_t *) pu1_buf; ps_layer_states = ps_ilp_mv_state->ps_layer_state; pu1_buf += u1_num_spatial_layers * sizeof(ps_ilp_mv_state->ps_layer_state[0]); i8_alloc_mem_size -= u1_num_spatial_layers * sizeof(ps_ilp_mv_state->ps_layer_state[0]); } else { ps_ilp_mv_state->ps_layer_state = ps_layer_states; } ASSERT(i8_alloc_mem_size >= 0); if(0 == i) { for(j = u1_num_spatial_layers - 1; j >= 1; j--) { ilp_mv_layer_state_t *ps_layer = &ps_ilp_mv_state->ps_layer_state[j]; WORD32 i4_layer_luma_wd = ((DOUBLE) u4_wd / pow(d_spatial_res_ratio, u1_num_spatial_layers - 1 - j)) + 0.99; WORD32 i4_layer_luma_ht = ((DOUBLE) u4_ht / pow(d_spatial_res_ratio, u1_num_spatial_layers - 1 - j)) + 0.99; WORD32 i4_layer_luma_mbs = (i4_layer_luma_wd / MB_SIZE) * (i4_layer_luma_ht / MB_SIZE); ps_layer->ps_mb_states = (ilp_mv_mb_state_t *) pu1_buf; aps_luma_mb_states[j] = ps_layer->ps_mb_states; pu1_buf += i4_layer_luma_mbs * sizeof(ps_layer->ps_mb_states[0]); i8_alloc_mem_size -= u1_num_spatial_layers * sizeof(ps_layer->ps_mb_states[0]); ASSERT(i8_alloc_mem_size >= 0); /* Asserts below verify that * 'ps_codec->s_svc_ilp_data.aps_layer_resampler_props' is initialised */ ASSERT(ps_codec->s_svc_ilp_data.aps_layer_resampler_props[Y][j].u4_mb_wd == MB_SIZE); ps_layer->ps_props = &ps_codec->s_svc_ilp_data.aps_layer_resampler_props[Y][j]; isvce_ilp_mv_layer_state_init(ps_layer, d_spatial_res_ratio, i4_layer_luma_wd, i4_layer_luma_ht); } } else { for(j = u1_num_spatial_layers - 1; j >= 1; j--) { ilp_mv_layer_state_t *ps_layer = &ps_ilp_mv_state->ps_layer_state[j]; ps_layer->ps_mb_states = aps_luma_mb_states[j]; ps_layer->ps_props = &ps_codec->s_svc_ilp_data.aps_layer_resampler_props[Y][j]; } } } } else { for(i = 0; i < i4_num_proc_ctxts; i++) { ps_codec->as_process[i].ps_svc_ilp_mv_ctxt = NULL; } } } static void isvce_get_ilp_mvs_for_me(svc_ilp_mv_ctxt_t *ps_ilp_mv_ctxt) { svc_layer_data_t *ps_ref_layer_data; ilp_mv_layer_state_t *ps_layer_state; ilp_mv_mb_state_t *ps_mb_state; isvce_mb_info_t *ps_ref_mb_info; coordinates_t s_frame_dims; coordinates_t s_frame_dims_in_mbs; coordinates_t s_ref_frame_dims; coordinates_t s_ref_frame_dims_in_mbs; bool b_is_mv_non_identical; WORD32 i, j, k; ilp_mv_constants_t *ps_ilp_mv_constants = &ps_ilp_mv_ctxt->s_ilp_mv_constants; ilp_mv_variables_t *ps_ilp_mv_variables = &ps_ilp_mv_ctxt->s_ilp_mv_variables; ilp_mv_outputs_t *ps_ilp_mv_outputs = &ps_ilp_mv_ctxt->s_ilp_mv_outputs; ilp_mv_state_t *ps_ilp_mv_state = (ilp_mv_state_t *) ps_ilp_mv_constants->pv_state; svc_ilp_data_t *ps_svc_ilp_data = ps_ilp_mv_variables->ps_svc_ilp_data; svc_au_data_t *ps_svc_au_data = ps_svc_ilp_data->ps_svc_au_data; coordinates_t *ps_mb_pos = &ps_ilp_mv_variables->s_mb_pos; const isvce_enc_pu_mv_t s_default_mv = {{0, 0}, -1}; UWORD8 u1_spatial_layer_id = ps_ilp_mv_variables->u1_spatial_layer_id; WORD32 i4_num_ilp_mvs = 0; s_frame_dims.i4_abscissa = ps_svc_ilp_data->ps_residual_bufs[u1_spatial_layer_id].u4_width; s_frame_dims.i4_ordinate = ps_svc_ilp_data->ps_residual_bufs[u1_spatial_layer_id].u4_height; s_frame_dims_in_mbs.i4_abscissa = s_frame_dims.i4_abscissa / MB_SIZE; s_frame_dims_in_mbs.i4_ordinate = s_frame_dims.i4_ordinate / MB_SIZE; s_ref_frame_dims.i4_abscissa = ps_svc_ilp_data->ps_residual_bufs[u1_spatial_layer_id - 1].u4_width; s_ref_frame_dims.i4_ordinate = ps_svc_ilp_data->ps_residual_bufs[u1_spatial_layer_id - 1].u4_height; s_ref_frame_dims_in_mbs.i4_abscissa = s_ref_frame_dims.i4_abscissa / MB_SIZE; s_ref_frame_dims_in_mbs.i4_ordinate = s_ref_frame_dims.i4_ordinate / MB_SIZE; ps_ref_layer_data = &ps_svc_au_data->ps_svc_layer_data[u1_spatial_layer_id - 1]; ps_layer_state = &ps_ilp_mv_state->ps_layer_state[u1_spatial_layer_id]; ps_mb_state = &ps_layer_state->ps_mb_states[ps_mb_pos->i4_abscissa + ps_mb_pos->i4_ordinate * s_frame_dims_in_mbs.i4_abscissa]; for(i = 0; i < MAX_PU_IN_MB_COL; i++) { for(j = 0; j < MAX_PU_IN_MB_ROW; j++) { b_is_mv_non_identical = true; ps_ilp_mv_outputs->s_ilp_me_cands.as_mv[i4_num_ilp_mvs][L0] = s_default_mv; ps_ilp_mv_outputs->s_ilp_me_cands.as_mv[i4_num_ilp_mvs][L1] = s_default_mv; ps_ref_mb_info = &ps_ref_layer_data->ps_mb_info[ps_mb_state->as_mb_positions[i][j].i4_abscissa + ps_mb_state->as_mb_positions[i][j].i4_ordinate * s_ref_frame_dims_in_mbs.i4_abscissa]; if((ps_ref_mb_info->u2_mb_type == P16x16) || (ps_ref_mb_info->u2_mb_type == B16x16)) { ps_ilp_mv_outputs->s_ilp_me_cands.e_mb_type[i4_num_ilp_mvs] = ps_ref_mb_info->u2_mb_type; ps_ilp_mv_outputs->s_ilp_me_cands.ae_pred_mode[i4_num_ilp_mvs] = ps_ref_mb_info->as_pu->u1_pred_mode; if(ps_ilp_mv_outputs->s_ilp_me_cands.ae_pred_mode[i4_num_ilp_mvs] != L0) { ps_ilp_mv_outputs->s_ilp_me_cands.as_mv[i4_num_ilp_mvs][L1] = ps_ref_mb_info->as_pu->as_me_info[L1]; ps_ilp_mv_outputs->s_ilp_me_cands.as_mv[i4_num_ilp_mvs][L1].s_mv.i2_mvx = (ps_ilp_mv_outputs->s_ilp_me_cands.as_mv[i4_num_ilp_mvs][L1].s_mv.i2_mvx * ps_layer_state->s_mv_scale.i4_abscissa + 32768) >> 16; ps_ilp_mv_outputs->s_ilp_me_cands.as_mv[i4_num_ilp_mvs][L1].s_mv.i2_mvy = (ps_ilp_mv_outputs->s_ilp_me_cands.as_mv[i4_num_ilp_mvs][L1].s_mv.i2_mvy * ps_layer_state->s_mv_scale.i4_ordinate + 32768) >> 16; } if(ps_ilp_mv_outputs->s_ilp_me_cands.ae_pred_mode[i4_num_ilp_mvs] != L1) { ps_ilp_mv_outputs->s_ilp_me_cands.as_mv[i4_num_ilp_mvs][L0] = ps_ref_mb_info->as_pu->as_me_info[L0]; ps_ilp_mv_outputs->s_ilp_me_cands.as_mv[i4_num_ilp_mvs][L0].s_mv.i2_mvx = (ps_ilp_mv_outputs->s_ilp_me_cands.as_mv[i4_num_ilp_mvs][L0].s_mv.i2_mvx * ps_layer_state->s_mv_scale.i4_abscissa + 32768) >> 16; ps_ilp_mv_outputs->s_ilp_me_cands.as_mv[i4_num_ilp_mvs][L0].s_mv.i2_mvy = (ps_ilp_mv_outputs->s_ilp_me_cands.as_mv[i4_num_ilp_mvs][L0].s_mv.i2_mvy * ps_layer_state->s_mv_scale.i4_ordinate + 32768) >> 16; } if(i4_num_ilp_mvs == 0) { i4_num_ilp_mvs++; } else { for(k = i4_num_ilp_mvs - 1; k >= 0; k--) { if((ps_ilp_mv_outputs->s_ilp_me_cands.e_mb_type[k] == ps_ilp_mv_outputs->s_ilp_me_cands.e_mb_type[i4_num_ilp_mvs]) && (ps_ilp_mv_outputs->s_ilp_me_cands.ae_pred_mode[k] == ps_ilp_mv_outputs->s_ilp_me_cands.ae_pred_mode[i4_num_ilp_mvs]) && isvce_check_identical_mv( ps_ilp_mv_outputs->s_ilp_me_cands.as_mv[k], ps_ilp_mv_outputs->s_ilp_me_cands.as_mv[i4_num_ilp_mvs], ps_ilp_mv_outputs->s_ilp_me_cands.ae_pred_mode[k])) { b_is_mv_non_identical = false; } } if(b_is_mv_non_identical) { i4_num_ilp_mvs++; } } } else { ps_ilp_mv_outputs->s_ilp_me_cands.e_mb_type[i4_num_ilp_mvs] = INVALID_MB_TYPE; } } } ps_ilp_mv_outputs->s_ilp_me_cands.u4_num_ilp_mvs = i4_num_ilp_mvs; for(i = 0; i < MAX_ILP_MV_IN_NBR_RGN; i++) { b_is_mv_non_identical = true; ps_ilp_mv_outputs->s_ilp_me_cands.as_mv[i4_num_ilp_mvs][L0] = s_default_mv; ps_ilp_mv_outputs->s_ilp_me_cands.as_mv[i4_num_ilp_mvs][L1] = s_default_mv; if(ps_mb_pos->i4_abscissa + gai1_nbr_ilp_mv_map[i][0] >= 0 && ps_mb_pos->i4_abscissa + gai1_nbr_ilp_mv_map[i][0] < s_frame_dims_in_mbs.i4_abscissa && ps_mb_pos->i4_ordinate + gai1_nbr_ilp_mv_map[i][1] >= 0 && ps_mb_pos->i4_ordinate + gai1_nbr_ilp_mv_map[i][1] < s_frame_dims_in_mbs.i4_ordinate) { ps_mb_state = &ps_layer_state->ps_mb_states[(ps_mb_pos->i4_abscissa + gai1_nbr_ilp_mv_map[i][0]) + (ps_mb_pos->i4_ordinate + gai1_nbr_ilp_mv_map[i][1]) * s_frame_dims_in_mbs.i4_abscissa]; ps_ref_mb_info = &ps_ref_layer_data->ps_mb_info[(ps_mb_state ->as_mb_positions[gai1_nbr_ilp_mv_map[i][2]] [gai1_nbr_ilp_mv_map[i][3]] .i4_abscissa) + ps_mb_state ->as_mb_positions[gai1_nbr_ilp_mv_map[i][2]] [gai1_nbr_ilp_mv_map[i][3]] .i4_ordinate * s_ref_frame_dims_in_mbs.i4_abscissa]; if((ps_ref_mb_info->u2_mb_type == P16x16) || (ps_ref_mb_info->u2_mb_type == B16x16)) { ps_ilp_mv_outputs->s_ilp_me_cands.e_mb_type[i4_num_ilp_mvs] = ps_ref_mb_info->u2_mb_type; ps_ilp_mv_outputs->s_ilp_me_cands.ae_pred_mode[i4_num_ilp_mvs] = ps_ref_mb_info->as_pu->u1_pred_mode; if(ps_ilp_mv_outputs->s_ilp_me_cands.ae_pred_mode[i4_num_ilp_mvs] != L0) { ps_ilp_mv_outputs->s_ilp_me_cands.as_mv[i4_num_ilp_mvs][L1] = ps_ref_mb_info->as_pu->as_me_info[L1]; ps_ilp_mv_outputs->s_ilp_me_cands.as_mv[i4_num_ilp_mvs][L1].s_mv.i2_mvx = (ps_ilp_mv_outputs->s_ilp_me_cands.as_mv[i4_num_ilp_mvs][L1].s_mv.i2_mvx * ps_layer_state->s_mv_scale.i4_abscissa + 32768) >> 16; ps_ilp_mv_outputs->s_ilp_me_cands.as_mv[i4_num_ilp_mvs][L1].s_mv.i2_mvy = (ps_ilp_mv_outputs->s_ilp_me_cands.as_mv[i4_num_ilp_mvs][L1].s_mv.i2_mvy * ps_layer_state->s_mv_scale.i4_ordinate + 32768) >> 16; } if(ps_ilp_mv_outputs->s_ilp_me_cands.ae_pred_mode[i4_num_ilp_mvs] != L1) { ps_ilp_mv_outputs->s_ilp_me_cands.as_mv[i4_num_ilp_mvs][L0] = ps_ref_mb_info->as_pu->as_me_info[L0]; ps_ilp_mv_outputs->s_ilp_me_cands.as_mv[i4_num_ilp_mvs][L0].s_mv.i2_mvx = (ps_ilp_mv_outputs->s_ilp_me_cands.as_mv[i4_num_ilp_mvs][L0].s_mv.i2_mvx * ps_layer_state->s_mv_scale.i4_abscissa + 32768) >> 16; ps_ilp_mv_outputs->s_ilp_me_cands.as_mv[i4_num_ilp_mvs][L0].s_mv.i2_mvy = (ps_ilp_mv_outputs->s_ilp_me_cands.as_mv[i4_num_ilp_mvs][L0].s_mv.i2_mvy * ps_layer_state->s_mv_scale.i4_ordinate + 32768) >> 16; } if(i4_num_ilp_mvs == 0) { i4_num_ilp_mvs++; } else { for(k = i4_num_ilp_mvs - 1; k >= 0; k--) { if((ps_ilp_mv_outputs->s_ilp_me_cands.e_mb_type[k] == ps_ilp_mv_outputs->s_ilp_me_cands.e_mb_type[i4_num_ilp_mvs]) && (ps_ilp_mv_outputs->s_ilp_me_cands.ae_pred_mode[k] == ps_ilp_mv_outputs->s_ilp_me_cands.ae_pred_mode[i4_num_ilp_mvs]) && isvce_check_identical_mv( ps_ilp_mv_outputs->s_ilp_me_cands.as_mv[k], ps_ilp_mv_outputs->s_ilp_me_cands.as_mv[i4_num_ilp_mvs], ps_ilp_mv_outputs->s_ilp_me_cands.ae_pred_mode[k])) b_is_mv_non_identical = false; } if(b_is_mv_non_identical) { i4_num_ilp_mvs++; } } } else { ps_ilp_mv_outputs->s_ilp_me_cands.e_mb_type[i4_num_ilp_mvs] = INVALID_MB_TYPE; } } } ps_ilp_mv_outputs->s_ilp_me_cands.u4_num_ilp_mvs_incl_nbrs = i4_num_ilp_mvs; } void isvce_get_mb_ilp_mv(svc_ilp_mv_ctxt_t *ps_ilp_mv_ctxt) { svc_layer_data_t *ps_ref_layer_data; ilp_mv_layer_state_t *ps_layer_state; ilp_mv_mb_state_t *ps_mb_state; isvce_mb_info_t *ps_ref_mb_info; coordinates_t s_frame_dims; coordinates_t s_frame_dims_in_mbs; coordinates_t s_ref_frame_dims; coordinates_t s_ref_frame_dims_in_mbs; WORD32 i, j; ilp_mv_constants_t *ps_ilp_mv_constants = &ps_ilp_mv_ctxt->s_ilp_mv_constants; ilp_mv_variables_t *ps_ilp_mv_variables = &ps_ilp_mv_ctxt->s_ilp_mv_variables; ilp_mv_outputs_t *ps_ilp_mv_outputs = &ps_ilp_mv_ctxt->s_ilp_mv_outputs; ilp_mv_state_t *ps_ilp_mv_state = (ilp_mv_state_t *) ps_ilp_mv_constants->pv_state; svc_ilp_data_t *ps_svc_ilp_data = ps_ilp_mv_variables->ps_svc_ilp_data; svc_au_data_t *ps_svc_au_data = ps_svc_ilp_data->ps_svc_au_data; coordinates_t *ps_mb_pos = &ps_ilp_mv_variables->s_mb_pos; const isvce_enc_pu_mv_t s_default_mv = {{0, 0}, -1}; UWORD8 u1_spatial_layer_id = ps_ilp_mv_variables->u1_spatial_layer_id; s_frame_dims.i4_abscissa = ps_svc_ilp_data->ps_residual_bufs[u1_spatial_layer_id].u4_width; s_frame_dims.i4_ordinate = ps_svc_ilp_data->ps_residual_bufs[u1_spatial_layer_id].u4_height; s_frame_dims_in_mbs.i4_abscissa = s_frame_dims.i4_abscissa / MB_SIZE; s_frame_dims_in_mbs.i4_ordinate = s_frame_dims.i4_ordinate / MB_SIZE; s_ref_frame_dims.i4_abscissa = ps_svc_ilp_data->ps_residual_bufs[u1_spatial_layer_id - 1].u4_width; s_ref_frame_dims.i4_ordinate = ps_svc_ilp_data->ps_residual_bufs[u1_spatial_layer_id - 1].u4_height; s_ref_frame_dims_in_mbs.i4_abscissa = s_ref_frame_dims.i4_abscissa / MB_SIZE; s_ref_frame_dims_in_mbs.i4_ordinate = s_ref_frame_dims.i4_ordinate / MB_SIZE; ps_ref_layer_data = &ps_svc_au_data->ps_svc_layer_data[u1_spatial_layer_id - 1]; ps_layer_state = &ps_ilp_mv_state->ps_layer_state[u1_spatial_layer_id]; ps_mb_state = &ps_layer_state->ps_mb_states[ps_mb_pos->i4_abscissa + ps_mb_pos->i4_ordinate * s_frame_dims_in_mbs.i4_abscissa]; ps_ilp_mv_outputs->s_ilp_mv.as_mv[0][L0] = s_default_mv; ps_ilp_mv_outputs->s_ilp_mv.as_mv[0][L1] = s_default_mv; ps_ref_mb_info = &ps_ref_layer_data->ps_mb_info[ps_mb_state->as_mb_positions[0][0].i4_abscissa + ps_mb_state->as_mb_positions[0][0].i4_ordinate * s_ref_frame_dims_in_mbs.i4_abscissa]; if((ps_ref_mb_info->u2_mb_type == P16x16) || (ps_ref_mb_info->u2_mb_type == B16x16)) { ps_ilp_mv_outputs->s_ilp_mv.e_mb_type = ps_ref_mb_info->u2_mb_type; ps_ilp_mv_outputs->s_ilp_mv.ae_pred_mode[0] = ps_ref_mb_info->as_pu->u1_pred_mode; if(ps_ilp_mv_outputs->s_ilp_mv.ae_pred_mode[0] != L0) { ps_ilp_mv_outputs->s_ilp_mv.as_mv[0][L1] = ps_ref_mb_info->as_pu->as_me_info[L1]; } if(ps_ilp_mv_outputs->s_ilp_mv.ae_pred_mode[0] != L1) { ps_ilp_mv_outputs->s_ilp_mv.as_mv[0][L0] = ps_ref_mb_info->as_pu->as_me_info[L0]; } } else { ps_ilp_mv_outputs->s_ilp_mv.e_mb_type = INVALID_MB_TYPE; } /* Function call to get non 16x16 ilp mvs for me candidates */ isvce_get_ilp_mvs_for_me(ps_ilp_mv_ctxt); /* Encoder supports only 16x16 partition. */ /* The code below ensures only 16x16 ILP MV's are used */ for(i = 0; i < MAX_PU_IN_MB_COL; i++) { for(j = 0; j < MAX_PU_IN_MB_ROW; j++) { bool b_unsupported_mv; ps_ref_mb_info = &ps_ref_layer_data->ps_mb_info[ps_mb_state->as_mb_positions[i][j].i4_abscissa + ps_mb_state->as_mb_positions[i][j].i4_ordinate * s_ref_frame_dims_in_mbs.i4_abscissa]; b_unsupported_mv = (ps_ref_mb_info->u2_mb_type != ps_ilp_mv_outputs->s_ilp_mv.e_mb_type) || (ps_ilp_mv_outputs->s_ilp_mv.ae_pred_mode[0] != ps_ref_mb_info->as_pu->u1_pred_mode) || !isvce_check_identical_mv(ps_ilp_mv_outputs->s_ilp_mv.as_mv[0], ps_ref_mb_info->as_pu->as_me_info, ps_ilp_mv_outputs->s_ilp_mv.ae_pred_mode[0]); if(b_unsupported_mv) { ps_ilp_mv_outputs->s_ilp_mv.as_mv[0][L0] = s_default_mv; ps_ilp_mv_outputs->s_ilp_mv.as_mv[0][L1] = s_default_mv; ps_ilp_mv_outputs->s_ilp_mv.e_mb_type = INVALID_MB_TYPE; return; } } } if(ps_ilp_mv_outputs->s_ilp_mv.e_mb_type != INVALID_MB_TYPE) { if(ps_ilp_mv_outputs->s_ilp_mv.ae_pred_mode[0] != L0) { ps_ilp_mv_outputs->s_ilp_mv.as_mv[0][L1].s_mv.i2_mvx = (ps_ilp_mv_outputs->s_ilp_mv.as_mv[0][L1].s_mv.i2_mvx * ps_layer_state->s_mv_scale.i4_abscissa + 32768) >> 16; ps_ilp_mv_outputs->s_ilp_mv.as_mv[0][L1].s_mv.i2_mvy = (ps_ilp_mv_outputs->s_ilp_mv.as_mv[0][L1].s_mv.i2_mvy * ps_layer_state->s_mv_scale.i4_ordinate + 32768) >> 16; } if(ps_ilp_mv_outputs->s_ilp_mv.ae_pred_mode[0] != L1) { ps_ilp_mv_outputs->s_ilp_mv.as_mv[0][L0].s_mv.i2_mvx = (ps_ilp_mv_outputs->s_ilp_mv.as_mv[0][L0].s_mv.i2_mvx * ps_layer_state->s_mv_scale.i4_abscissa + 32768) >> 16; ps_ilp_mv_outputs->s_ilp_mv.as_mv[0][L0].s_mv.i2_mvy = (ps_ilp_mv_outputs->s_ilp_mv.as_mv[0][L0].s_mv.i2_mvy * ps_layer_state->s_mv_scale.i4_ordinate + 32768) >> 16; } } else { ps_ilp_mv_outputs->s_ilp_mv.e_mb_type = INVALID_MB_TYPE; ps_ilp_mv_outputs->s_ilp_mv.ae_pred_mode[0] = INVALID_PRED_MODE; } } void isvce_mvp_idx_eval(isvce_mb_info_t *ps_mb_info, isvce_enc_pu_mv_t *ps_spatial_mvp, isvce_enc_pu_mv_t *ps_ilp_mvp, UWORD8 *pu1_mvd_costs) { if(USE_ILP_MV_AS_MVP && ps_ilp_mvp && !ps_mb_info->u1_is_intra && (ps_mb_info->u2_mb_type != PSKIP) && (ps_mb_info->u2_mb_type != BSKIP) && (ps_mb_info->u2_mb_type != BASE_MODE)) { isvce_enc_pu_mv_t *ps_mv; isvce_enc_pu_mv_t *aps_mvps[2]; WORD32 ai4_mvd_costs[2]; WORD32 i, j; for(i = 0; i < NUM_PRED_DIRS; i++) { PRED_MODE_T e_pred_mode = (PRED_MODE_T) i; PRED_MODE_T e_cmpl_pred_mode = (e_pred_mode == L0) ? L1 : L0; if(ps_mb_info->as_pu->u1_pred_mode != e_pred_mode) { ps_mv = &ps_mb_info->as_pu->as_me_info[e_cmpl_pred_mode]; aps_mvps[0] = &ps_spatial_mvp[e_cmpl_pred_mode]; aps_mvps[1] = &ps_ilp_mvp[e_cmpl_pred_mode]; for(j = 0; j < 2; j++) { if((aps_mvps[j]->i1_ref_idx != -1) && (!j || ((j == 1) && (ps_mv->i1_ref_idx == aps_mvps[j]->i1_ref_idx)))) { ai4_mvd_costs[j] = pu1_mvd_costs[ps_mv->s_mv.i2_mvx - aps_mvps[j]->s_mv.i2_mvx] + pu1_mvd_costs[ps_mv->s_mv.i2_mvy - aps_mvps[j]->s_mv.i2_mvy]; } else { ai4_mvd_costs[j] = INT32_MAX; } } ps_mb_info->as_pu->au1_mvp_idx[e_cmpl_pred_mode] = ai4_mvd_costs[0] > ai4_mvd_costs[1]; } else { ps_mb_info->as_pu->au1_mvp_idx[e_cmpl_pred_mode] = 0; } } } else { ps_mb_info->as_pu->au1_mvp_idx[L0] = 0; ps_mb_info->as_pu->au1_mvp_idx[L1] = 0; } }