aosp12/external/libhevc/encoder/ihevce_enc_loop_inter_mode_...

2746 lines
93 KiB
C

/******************************************************************************
*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*****************************************************************************
* Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
*/
/*!
******************************************************************************
* \file ihevce_enc_loop_inter_mode_sifter.c
*
* \brief
* This file contains functions for selecting best inter candidates for RDOPT evaluation
*
* \date
* 10/09/2014
*
******************************************************************************
*/
/*****************************************************************************/
/* 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_macros.h"
#include "ihevc_debug.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_hle_interface.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_ipe_instr_set_router.h"
#include "ihevce_decomp_pre_intra_structs.h"
#include "ihevce_decomp_pre_intra_pass.h"
#include "ihevce_enc_loop_structs.h"
#include "ihevce_global_tables.h"
#include "ihevce_nbr_avail.h"
#include "ihevce_enc_loop_utils.h"
#include "ihevce_bs_compute_ctb.h"
#include "ihevce_cabac_rdo.h"
#include "ihevce_dep_mngr_interface.h"
#include "ihevce_enc_loop_pass.h"
#include "ihevce_rc_enc_structs.h"
#include "ihevce_common_utils.h"
#include "ihevce_stasino_helpers.h"
#include "hme_datatype.h"
#include "hme_common_defs.h"
#include "hme_common_utils.h"
#include "hme_interface.h"
#include "hme_defs.h"
#include "ihevce_me_instr_set_router.h"
#include "hme_err_compute.h"
#include "hme_globals.h"
#include "ihevce_mv_pred.h"
#include "ihevce_mv_pred_merge.h"
#include "ihevce_inter_pred.h"
#include "ihevce_enc_loop_inter_mode_sifter.h"
/*****************************************************************************/
/* Function Definitions */
/*****************************************************************************/
static WORD32 ihevce_get_num_part_types_in_me_cand_list(
cu_inter_cand_t *ps_me_cand_list,
UWORD8 *pu1_part_type_ref_cand,
UWORD8 *pu1_idx_ref_cand,
UWORD8 *pu1_diff_skip_cand_flag,
WORD8 *pi1_skip_cand_from_merge_idx,
WORD8 *pi1_final_skip_cand_merge_idx,
UWORD8 u1_max_num_part_types_to_select,
UWORD8 u1_num_me_cands)
{
UWORD8 i, j;
UWORD8 u1_num_unique_parts = 0;
for(i = 0; i < u1_num_me_cands; i++)
{
UWORD8 u1_cur_part_type = ps_me_cand_list[i].b3_part_size;
UWORD8 u1_is_unique = 1;
if(u1_num_unique_parts >= u1_max_num_part_types_to_select)
{
return u1_num_unique_parts;
}
/* loop to check if the current cand is already present in the list */
for(j = 0; j < u1_num_unique_parts; j++)
{
if(u1_cur_part_type == pu1_part_type_ref_cand[j])
{
u1_is_unique = 0;
break;
}
}
if(u1_is_unique)
{
if(SIZE_2Nx2N == u1_cur_part_type)
{
*pu1_diff_skip_cand_flag = 0;
*pi1_skip_cand_from_merge_idx = u1_num_unique_parts;
*pi1_final_skip_cand_merge_idx = u1_num_unique_parts;
}
pu1_part_type_ref_cand[u1_num_unique_parts] = u1_cur_part_type;
pu1_idx_ref_cand[u1_num_unique_parts] = i;
u1_num_unique_parts++;
}
}
return u1_num_unique_parts;
}
static WORD32 ihevce_compute_inter_pred_and_cost(
inter_pred_ctxt_t *ps_mc_ctxt,
PF_LUMA_INTER_PRED_PU pf_luma_inter_pred_pu,
PF_SAD_FXN_T pf_sad_func,
pu_t *ps_pu,
void *pv_src,
void *pv_pred,
WORD32 i4_src_stride,
WORD32 i4_pred_stride,
UWORD8 u1_compute_error,
ihevce_cmn_opt_func_t *ps_cmn_utils_optimised_function_list)
{
IV_API_CALL_STATUS_T u1_is_valid_mv;
WORD32 i4_error;
u1_is_valid_mv = pf_luma_inter_pred_pu(ps_mc_ctxt, ps_pu, pv_pred, i4_pred_stride, 0);
if(u1_compute_error)
{
if(IV_SUCCESS == u1_is_valid_mv)
{
err_prms_t s_err_prms;
s_err_prms.i4_blk_ht = (ps_pu->b4_ht + 1) << 2;
s_err_prms.i4_blk_wd = (ps_pu->b4_wd + 1) << 2;
s_err_prms.pu1_inp = (UWORD8 *)pv_src;
s_err_prms.pu2_inp = (UWORD16 *)pv_src;
s_err_prms.pu1_ref = (UWORD8 *)pv_pred;
s_err_prms.pu2_ref = (UWORD16 *)pv_pred;
s_err_prms.i4_inp_stride = i4_src_stride;
s_err_prms.i4_ref_stride = i4_pred_stride;
s_err_prms.pi4_sad_grid = &i4_error;
s_err_prms.ps_cmn_utils_optimised_function_list = ps_cmn_utils_optimised_function_list;
pf_sad_func(&s_err_prms);
}
else
{
/* max 32 bit satd */
i4_error = INT_MAX;
}
return i4_error;
}
return INT_MAX;
}
static WORD32 ihevce_determine_best_merge_pu(
merge_prms_t *ps_prms,
pu_t *ps_pu_merge,
pu_t *ps_pu_me,
void *pv_src,
WORD32 i4_me_cand_cost,
WORD32 i4_pred_buf_offset,
UWORD8 u1_num_cands,
UWORD8 u1_part_id,
UWORD8 u1_force_pred_evaluation)
{
pu_t *ps_pu;
INTER_CANDIDATE_ID_T e_cand_id;
UWORD8 i;
UWORD8 u1_best_pred_mode;
WORD32 i4_mean;
UWORD32 u4_cur_variance, u4_best_variance;
merge_cand_list_t *ps_list = ps_prms->ps_list;
inter_pred_ctxt_t *ps_mc_ctxt = ps_prms->ps_mc_ctxt;
PF_LUMA_INTER_PRED_PU pf_luma_inter_pred_pu = ps_prms->pf_luma_inter_pred_pu;
PF_SAD_FXN_T pf_sad_fxn = ps_prms->pf_sad_fxn;
ihevce_cmn_opt_func_t *ps_cmn_utils_optimised_function_list =
ps_prms->ps_cmn_utils_optimised_function_list;
WORD32(*pai4_noise_term)[MAX_NUM_INTER_PARTS] = ps_prms->pai4_noise_term;
UWORD32(*pau4_pred_variance)[MAX_NUM_INTER_PARTS] = ps_prms->pau4_pred_variance;
WORD32 i4_alpha_stim_multiplier = ps_prms->i4_alpha_stim_multiplier;
UWORD32 *pu4_src_variance = ps_prms->pu4_src_variance;
UWORD8 u1_is_cu_noisy = ps_prms->u1_is_cu_noisy;
UWORD8 u1_is_hbd = ps_prms->u1_is_hbd;
UWORD8 *pu1_valid_merge_indices = ps_prms->au1_valid_merge_indices;
void **ppv_pred_buf_list = ps_prms->ppv_pred_buf_list;
UWORD8 *pu1_merge_pred_buf_array = ps_prms->pu1_merge_pred_buf_array;
UWORD8(*pau1_best_pred_buf_id)[MAX_NUM_INTER_PARTS] = ps_prms->pau1_best_pred_buf_id;
UWORD8 u1_merge_idx_cabac_model = ps_prms->u1_merge_idx_cabac_model;
WORD32 i4_lambda = ps_prms->i4_lambda;
WORD32 i4_src_stride = ps_prms->i4_src_stride;
WORD32 i4_pred_stride = ps_prms->i4_pred_stride;
UWORD8 u1_max_cands = ps_prms->u1_max_cands;
UWORD8 u1_best_buf_id = pu1_merge_pred_buf_array[0];
UWORD8 u1_cur_buf_id = pu1_merge_pred_buf_array[1];
UWORD8 u1_best_cand_id = UCHAR_MAX;
WORD32 i4_best_cost = INT_MAX;
WORD32 i4_cur_noise_term = 0;
WORD32 i4_best_noise_term = 0;
ps_pu = ps_pu_merge;
e_cand_id = MERGE_DERIVED;
ASSERT(ps_pu->b1_merge_flag);
for(i = 0; i < u1_num_cands; i++)
{
WORD32 i4_cur_cost;
void *pv_pred = (UWORD8 *)ppv_pred_buf_list[u1_cur_buf_id] + i4_pred_buf_offset;
UWORD8 u1_is_pred_available = 0;
if(!ps_prms->u1_use_merge_cand_from_top_row && ps_prms->pu1_is_top_used[i])
{
continue;
}
ps_pu->mv = ps_list[i].mv;
ps_pu->b3_merge_idx = pu1_valid_merge_indices[i];
/* set the prediction mode */
if(ps_list[i].u1_pred_flag_l0 && ps_list[i].u1_pred_flag_l1)
{
ps_pu->b2_pred_mode = PRED_BI;
}
else if(ps_list[i].u1_pred_flag_l0)
{
ps_pu->b2_pred_mode = PRED_L0;
}
else
{
ps_pu->b2_pred_mode = PRED_L1;
}
/* 8x8 SMPs should not have bipred mode as per std */
{
WORD32 i4_part_wd, i4_part_ht;
i4_part_wd = (ps_pu->b4_wd + 1) << 2;
i4_part_ht = (ps_pu->b4_ht + 1) << 2;
if((PRED_BI == ps_pu->b2_pred_mode) && ((i4_part_wd + i4_part_ht) < 16))
{
continue;
}
}
if((!u1_force_pred_evaluation) &&
(ihevce_compare_pu_mv_t(
&ps_pu->mv, &ps_pu_me->mv, ps_pu->b2_pred_mode, ps_pu_me->b2_pred_mode)))
{
i4_cur_cost = i4_me_cand_cost;
u1_is_pred_available = 1;
if((i4_cur_cost < INT_MAX) && u1_is_cu_noisy && i4_alpha_stim_multiplier)
{
i4_cur_noise_term = pai4_noise_term[ME_OR_SKIP_DERIVED][u1_part_id];
u4_cur_variance = pau4_pred_variance[ME_OR_SKIP_DERIVED][u1_part_id];
}
}
else
{
i4_cur_cost = ihevce_compute_inter_pred_and_cost(
ps_mc_ctxt,
pf_luma_inter_pred_pu,
pf_sad_fxn,
ps_pu,
pv_src,
pv_pred,
i4_src_stride,
i4_pred_stride,
1,
ps_cmn_utils_optimised_function_list);
if((i4_cur_cost < INT_MAX) && u1_is_cu_noisy && i4_alpha_stim_multiplier)
{
ihevce_calc_variance(
pv_pred,
i4_pred_stride,
&i4_mean,
&u4_cur_variance,
(ps_pu->b4_ht + 1) << 2,
(ps_pu->b4_wd + 1) << 2,
u1_is_hbd,
0);
i4_cur_noise_term = ihevce_compute_noise_term(
i4_alpha_stim_multiplier, pu4_src_variance[u1_part_id], u4_cur_variance);
MULTIPLY_STIM_WITH_DISTORTION(
i4_cur_cost, i4_cur_noise_term, STIM_Q_FORMAT, ALPHA_Q_FORMAT);
}
}
if(i4_cur_cost < INT_MAX)
{
WORD32 i4_merge_idx_cost = 0;
COMPUTE_MERGE_IDX_COST(
u1_merge_idx_cabac_model, i, u1_max_cands, i4_lambda, i4_merge_idx_cost);
i4_cur_cost += i4_merge_idx_cost;
}
if(i4_cur_cost < i4_best_cost)
{
i4_best_cost = i4_cur_cost;
if(u1_is_cu_noisy && i4_alpha_stim_multiplier)
{
i4_best_noise_term = i4_cur_noise_term;
u4_best_variance = u4_cur_variance;
}
u1_best_cand_id = i;
u1_best_pred_mode = ps_pu->b2_pred_mode;
if(u1_is_pred_available)
{
pau1_best_pred_buf_id[e_cand_id][u1_part_id] =
pau1_best_pred_buf_id[ME_OR_SKIP_DERIVED][u1_part_id];
}
else
{
SWAP(u1_best_buf_id, u1_cur_buf_id);
pau1_best_pred_buf_id[e_cand_id][u1_part_id] = u1_best_buf_id;
}
}
}
if(u1_best_cand_id != UCHAR_MAX)
{
ps_pu->mv = ps_list[u1_best_cand_id].mv;
ps_pu->b2_pred_mode = u1_best_pred_mode;
ps_pu->b3_merge_idx = pu1_valid_merge_indices[u1_best_cand_id];
if(u1_is_cu_noisy && i4_alpha_stim_multiplier)
{
pai4_noise_term[MERGE_DERIVED][u1_part_id] = i4_best_noise_term;
pau4_pred_variance[MERGE_DERIVED][u1_part_id] = u4_best_variance;
}
}
return i4_best_cost;
}
static WORD8 ihevce_merge_cand_pred_buffer_preparation(
void **ppv_pred_buf_list,
cu_inter_cand_t *ps_cand,
UWORD8 (*pau1_final_pred_buf_id)[MAX_NUM_INTER_PARTS],
WORD32 i4_pred_stride,
UWORD8 u1_cu_size,
UWORD8 u1_part_type,
UWORD8 u1_num_bytes_per_pel,
FT_COPY_2D *pf_copy_2d)
{
WORD32 i4_part_wd;
WORD32 i4_part_ht;
WORD32 i4_part_wd_pu2;
WORD32 i4_part_ht_pu2;
WORD32 i4_buf_offset;
UWORD8 *pu1_pred_src;
UWORD8 *pu1_pred_dst;
WORD8 i1_retval = pau1_final_pred_buf_id[MERGE_DERIVED][0];
WORD32 i4_stride = i4_pred_stride * u1_num_bytes_per_pel;
if((0 == u1_part_type) ||
(pau1_final_pred_buf_id[MERGE_DERIVED][0] == pau1_final_pred_buf_id[MERGE_DERIVED][1]))
{
ps_cand->pu1_pred_data =
(UWORD8 *)ppv_pred_buf_list[pau1_final_pred_buf_id[MERGE_DERIVED][0]];
ps_cand->pu2_pred_data =
(UWORD16 *)ppv_pred_buf_list[pau1_final_pred_buf_id[MERGE_DERIVED][0]];
ps_cand->i4_pred_data_stride = i4_pred_stride;
i1_retval = pau1_final_pred_buf_id[MERGE_DERIVED][0];
}
else if(pau1_final_pred_buf_id[MERGE_DERIVED][0] == pau1_final_pred_buf_id[ME_OR_SKIP_DERIVED][0])
{
i4_part_wd = (ps_cand->as_inter_pu[0].b4_wd + 1) << 2;
i4_part_ht = (ps_cand->as_inter_pu[0].b4_ht + 1) << 2;
i4_buf_offset = 0;
pu1_pred_src = (UWORD8 *)ppv_pred_buf_list[pau1_final_pred_buf_id[ME_OR_SKIP_DERIVED][0]] +
i4_buf_offset;
pu1_pred_dst =
(UWORD8 *)ppv_pred_buf_list[pau1_final_pred_buf_id[MERGE_DERIVED][1]] + i4_buf_offset;
pf_copy_2d(
pu1_pred_dst,
i4_stride,
pu1_pred_src,
i4_stride,
i4_part_wd * u1_num_bytes_per_pel,
i4_part_ht);
ps_cand->pu1_pred_data =
(UWORD8 *)ppv_pred_buf_list[pau1_final_pred_buf_id[MERGE_DERIVED][1]];
ps_cand->pu2_pred_data =
(UWORD16 *)ppv_pred_buf_list[pau1_final_pred_buf_id[MERGE_DERIVED][1]];
ps_cand->i4_pred_data_stride = i4_pred_stride;
i1_retval = pau1_final_pred_buf_id[MERGE_DERIVED][1];
}
else if(pau1_final_pred_buf_id[MERGE_DERIVED][1] == pau1_final_pred_buf_id[ME_OR_SKIP_DERIVED][1])
{
i4_part_wd = (ps_cand->as_inter_pu[0].b4_wd + 1) << 2;
i4_part_ht = (ps_cand->as_inter_pu[0].b4_ht + 1) << 2;
i4_buf_offset = (i4_part_ht < u1_cu_size) * i4_part_ht * i4_pred_stride +
(i4_part_wd < u1_cu_size) * i4_part_wd;
i4_buf_offset *= u1_num_bytes_per_pel;
i4_part_wd = (ps_cand->as_inter_pu[1].b4_wd + 1) << 2;
i4_part_ht = (ps_cand->as_inter_pu[1].b4_ht + 1) << 2;
pu1_pred_src = (UWORD8 *)ppv_pred_buf_list[pau1_final_pred_buf_id[ME_OR_SKIP_DERIVED][1]] +
i4_buf_offset;
pu1_pred_dst =
(UWORD8 *)ppv_pred_buf_list[pau1_final_pred_buf_id[MERGE_DERIVED][0]] + i4_buf_offset;
pf_copy_2d(
pu1_pred_dst,
i4_stride,
pu1_pred_src,
i4_stride,
i4_part_wd * u1_num_bytes_per_pel,
i4_part_ht);
ps_cand->pu1_pred_data =
(UWORD8 *)ppv_pred_buf_list[pau1_final_pred_buf_id[MERGE_DERIVED][0]];
ps_cand->pu2_pred_data =
(UWORD16 *)ppv_pred_buf_list[pau1_final_pred_buf_id[MERGE_DERIVED][0]];
ps_cand->i4_pred_data_stride = i4_pred_stride;
i1_retval = pau1_final_pred_buf_id[MERGE_DERIVED][0];
}
else
{
i4_part_wd = (ps_cand->as_inter_pu[0].b4_wd + 1) << 2;
i4_part_ht = (ps_cand->as_inter_pu[0].b4_ht + 1) << 2;
i4_part_wd_pu2 = (ps_cand->as_inter_pu[1].b4_wd + 1) << 2;
i4_part_ht_pu2 = (ps_cand->as_inter_pu[1].b4_ht + 1) << 2;
switch((PART_TYPE_T)u1_part_type)
{
case PRT_2NxN:
case PRT_Nx2N:
case PRT_2NxnU:
case PRT_nLx2N:
{
pu1_pred_src = (UWORD8 *)ppv_pred_buf_list[pau1_final_pred_buf_id[MERGE_DERIVED][0]];
pu1_pred_dst = (UWORD8 *)ppv_pred_buf_list[pau1_final_pred_buf_id[MERGE_DERIVED][1]];
ps_cand->pu1_pred_data =
(UWORD8 *)ppv_pred_buf_list[pau1_final_pred_buf_id[MERGE_DERIVED][1]];
ps_cand->pu2_pred_data =
(UWORD16 *)ppv_pred_buf_list[pau1_final_pred_buf_id[MERGE_DERIVED][1]];
i1_retval = pau1_final_pred_buf_id[MERGE_DERIVED][1];
break;
}
case PRT_nRx2N:
case PRT_2NxnD:
{
i4_buf_offset = (i4_part_ht < u1_cu_size) * i4_part_ht * i4_pred_stride +
(i4_part_wd < u1_cu_size) * i4_part_wd;
i4_buf_offset *= u1_num_bytes_per_pel;
pu1_pred_src = (UWORD8 *)ppv_pred_buf_list[pau1_final_pred_buf_id[MERGE_DERIVED][1]] +
i4_buf_offset;
pu1_pred_dst = (UWORD8 *)ppv_pred_buf_list[pau1_final_pred_buf_id[MERGE_DERIVED][0]] +
i4_buf_offset;
i4_part_wd = i4_part_wd_pu2;
i4_part_ht = i4_part_ht_pu2;
ps_cand->pu1_pred_data =
(UWORD8 *)ppv_pred_buf_list[pau1_final_pred_buf_id[MERGE_DERIVED][0]];
ps_cand->pu2_pred_data =
(UWORD16 *)ppv_pred_buf_list[pau1_final_pred_buf_id[MERGE_DERIVED][0]];
i1_retval = pau1_final_pred_buf_id[MERGE_DERIVED][0];
break;
}
}
pf_copy_2d(
pu1_pred_dst,
i4_stride,
pu1_pred_src,
i4_stride,
i4_part_wd * u1_num_bytes_per_pel,
i4_part_ht);
ps_cand->i4_pred_data_stride = i4_pred_stride;
}
return i1_retval;
}
static WORD8 ihevce_mixed_mode_cand_type1_pred_buffer_preparation(
void **ppv_pred_buf_list,
cu_inter_cand_t *ps_cand,
UWORD8 (*pau1_final_pred_buf_id)[MAX_NUM_INTER_PARTS],
UWORD8 *pu1_merge_pred_buf_idx_array,
WORD32 i4_pred_stride,
UWORD8 u1_me_pred_buf_id,
UWORD8 u1_merge_pred_buf_id,
UWORD8 u1_type0_cand_is_valid,
UWORD8 u1_cu_size,
UWORD8 u1_part_type,
UWORD8 u1_num_bytes_per_pel,
FT_COPY_2D *pf_copy_2d)
{
WORD32 i4_part_wd;
WORD32 i4_part_ht;
WORD32 i4_part_wd_pu2;
WORD32 i4_part_ht_pu2;
UWORD8 *pu1_pred_src;
UWORD8 *pu1_pred_dst = NULL;
WORD8 i1_retval = pau1_final_pred_buf_id[ME_OR_SKIP_DERIVED][0];
WORD32 i4_stride = i4_pred_stride * u1_num_bytes_per_pel;
ASSERT(0 != u1_part_type);
i4_part_wd = (ps_cand->as_inter_pu[0].b4_wd + 1) << 2;
i4_part_ht = (ps_cand->as_inter_pu[0].b4_ht + 1) << 2;
i4_part_wd_pu2 = (ps_cand->as_inter_pu[1].b4_wd + 1) << 2;
i4_part_ht_pu2 = (ps_cand->as_inter_pu[1].b4_ht + 1) << 2;
if(pau1_final_pred_buf_id[MIXED_MODE_TYPE1][1] == pau1_final_pred_buf_id[ME_OR_SKIP_DERIVED][1])
{
ps_cand->pu1_pred_data =
(UWORD8 *)ppv_pred_buf_list[pau1_final_pred_buf_id[ME_OR_SKIP_DERIVED][0]];
ps_cand->pu2_pred_data =
(UWORD16 *)ppv_pred_buf_list[pau1_final_pred_buf_id[ME_OR_SKIP_DERIVED][0]];
ps_cand->i4_pred_data_stride = i4_pred_stride;
i1_retval = pau1_final_pred_buf_id[ME_OR_SKIP_DERIVED][0];
return i1_retval;
}
else
{
UWORD8 u1_bitfield = ((u1_merge_pred_buf_id == UCHAR_MAX) << 3) |
((u1_me_pred_buf_id == UCHAR_MAX) << 2) |
((!u1_type0_cand_is_valid) << 1) |
(pau1_final_pred_buf_id[MIXED_MODE_TYPE1][1] ==
pau1_final_pred_buf_id[MERGE_DERIVED][1]);
WORD32 i4_buf_offset = (i4_part_ht < u1_cu_size) * i4_part_ht * i4_pred_stride +
(i4_part_wd < u1_cu_size) * i4_part_wd;
i4_buf_offset *= u1_num_bytes_per_pel;
switch(u1_bitfield)
{
case 15:
case 14:
case 6:
{
switch((PART_TYPE_T)u1_part_type)
{
case PRT_2NxN:
case PRT_Nx2N:
case PRT_2NxnU:
case PRT_nLx2N:
{
pu1_pred_src =
(UWORD8 *)ppv_pred_buf_list[pau1_final_pred_buf_id[ME_OR_SKIP_DERIVED][0]];
pu1_pred_dst =
(UWORD8 *)ppv_pred_buf_list[pau1_final_pred_buf_id[MIXED_MODE_TYPE1][1]];
i1_retval = pau1_final_pred_buf_id[MIXED_MODE_TYPE1][1];
break;
}
case PRT_nRx2N:
case PRT_2NxnD:
{
pu1_pred_src =
(UWORD8 *)ppv_pred_buf_list[pau1_final_pred_buf_id[MIXED_MODE_TYPE1][1]] +
i4_buf_offset;
pu1_pred_dst =
(UWORD8 *)ppv_pred_buf_list[pau1_final_pred_buf_id[ME_OR_SKIP_DERIVED][0]] +
i4_buf_offset;
i4_part_wd = i4_part_wd_pu2;
i4_part_ht = i4_part_ht_pu2;
i1_retval = pau1_final_pred_buf_id[ME_OR_SKIP_DERIVED][0];
break;
}
}
ps_cand->pu1_pred_data = (UWORD8 *)ppv_pred_buf_list[i1_retval];
ps_cand->pu2_pred_data = (UWORD16 *)ppv_pred_buf_list[i1_retval];
ps_cand->i4_pred_data_stride = i4_pred_stride;
pf_copy_2d(
pu1_pred_dst,
i4_stride,
pu1_pred_src,
i4_stride,
i4_part_wd * u1_num_bytes_per_pel,
i4_part_ht);
break;
}
case 13:
case 9:
case 5:
{
UWORD8 i;
for(i = 0; i < 3; i++)
{
if((pu1_merge_pred_buf_idx_array[i] != pau1_final_pred_buf_id[MERGE_DERIVED][1]) &&
(pu1_merge_pred_buf_idx_array[i] != pau1_final_pred_buf_id[MERGE_DERIVED][0]))
{
pu1_pred_dst = (UWORD8 *)ppv_pred_buf_list[pu1_merge_pred_buf_idx_array[i]] +
i4_buf_offset;
i1_retval = pu1_merge_pred_buf_idx_array[i];
break;
}
}
pu1_pred_src = (UWORD8 *)ppv_pred_buf_list[pau1_final_pred_buf_id[MERGE_DERIVED][1]] +
i4_buf_offset;
pf_copy_2d(
pu1_pred_dst,
i4_stride,
pu1_pred_src,
i4_stride,
i4_part_wd_pu2 * u1_num_bytes_per_pel,
i4_part_ht_pu2);
/* Copy PU1 */
pu1_pred_src =
(UWORD8 *)ppv_pred_buf_list[pau1_final_pred_buf_id[ME_OR_SKIP_DERIVED][0]];
pu1_pred_dst = (UWORD8 *)ppv_pred_buf_list[i1_retval];
pf_copy_2d(
pu1_pred_dst,
i4_stride,
pu1_pred_src,
i4_stride,
i4_part_wd * u1_num_bytes_per_pel,
i4_part_ht);
ps_cand->pu1_pred_data = (UWORD8 *)ppv_pred_buf_list[i1_retval];
ps_cand->pu2_pred_data = (UWORD16 *)ppv_pred_buf_list[i1_retval];
ps_cand->i4_pred_data_stride = i4_pred_stride;
break;
}
case 12:
case 10:
case 8:
case 4:
case 2:
case 0:
{
pu1_pred_src =
(UWORD8 *)ppv_pred_buf_list[pau1_final_pred_buf_id[ME_OR_SKIP_DERIVED][0]];
pu1_pred_dst = (UWORD8 *)ppv_pred_buf_list[pau1_final_pred_buf_id[MIXED_MODE_TYPE1][1]];
i1_retval = pau1_final_pred_buf_id[MIXED_MODE_TYPE1][1];
ps_cand->pu1_pred_data = (UWORD8 *)ppv_pred_buf_list[i1_retval];
ps_cand->pu2_pred_data = (UWORD16 *)ppv_pred_buf_list[i1_retval];
ps_cand->i4_pred_data_stride = i4_pred_stride;
pf_copy_2d(
pu1_pred_dst,
i4_stride,
pu1_pred_src,
i4_stride,
i4_part_wd * u1_num_bytes_per_pel,
i4_part_ht);
break;
}
case 11:
{
pu1_pred_src =
(UWORD8 *)ppv_pred_buf_list[pau1_final_pred_buf_id[ME_OR_SKIP_DERIVED][0]];
pu1_pred_dst = (UWORD8 *)ppv_pred_buf_list[pau1_final_pred_buf_id[MERGE_DERIVED][1]];
i1_retval = pau1_final_pred_buf_id[MERGE_DERIVED][1];
ps_cand->pu1_pred_data = (UWORD8 *)ppv_pred_buf_list[i1_retval];
ps_cand->pu2_pred_data = (UWORD16 *)ppv_pred_buf_list[i1_retval];
ps_cand->i4_pred_data_stride = i4_pred_stride;
pf_copy_2d(
pu1_pred_dst,
i4_stride,
pu1_pred_src,
i4_stride,
i4_part_wd * u1_num_bytes_per_pel,
i4_part_ht);
break;
}
case 7:
{
pu1_pred_src = (UWORD8 *)ppv_pred_buf_list[pau1_final_pred_buf_id[MERGE_DERIVED][1]] +
i4_buf_offset;
pu1_pred_dst =
(UWORD8 *)ppv_pred_buf_list[pau1_final_pred_buf_id[ME_OR_SKIP_DERIVED][1]] +
i4_buf_offset;
i1_retval = pau1_final_pred_buf_id[ME_OR_SKIP_DERIVED][1];
ps_cand->pu1_pred_data = (UWORD8 *)ppv_pred_buf_list[i1_retval];
ps_cand->pu2_pred_data = (UWORD16 *)ppv_pred_buf_list[i1_retval];
ps_cand->i4_pred_data_stride = i4_pred_stride;
pf_copy_2d(
pu1_pred_dst,
i4_stride,
pu1_pred_src,
i4_stride,
i4_part_wd_pu2 * u1_num_bytes_per_pel,
i4_part_ht_pu2);
break;
}
case 3:
case 1:
{
if((u1_merge_pred_buf_id == pau1_final_pred_buf_id[MERGE_DERIVED][0]) &&
(u1_merge_pred_buf_id != pau1_final_pred_buf_id[MERGE_DERIVED][1]))
{
pu1_pred_src =
(UWORD8 *)ppv_pred_buf_list[pau1_final_pred_buf_id[ME_OR_SKIP_DERIVED][0]];
pu1_pred_dst =
(UWORD8 *)ppv_pred_buf_list[pau1_final_pred_buf_id[MERGE_DERIVED][1]];
i1_retval = pau1_final_pred_buf_id[MERGE_DERIVED][1];
ps_cand->pu1_pred_data = (UWORD8 *)ppv_pred_buf_list[i1_retval];
ps_cand->pu2_pred_data = (UWORD16 *)ppv_pred_buf_list[i1_retval];
ps_cand->i4_pred_data_stride = i4_pred_stride;
pf_copy_2d(
pu1_pred_dst,
i4_stride,
pu1_pred_src,
i4_stride,
i4_part_wd * u1_num_bytes_per_pel,
i4_part_ht);
}
else
{
UWORD8 i;
for(i = 0; i < 3; i++)
{
if((pu1_merge_pred_buf_idx_array[i] !=
pau1_final_pred_buf_id[MERGE_DERIVED][1]) &&
(pu1_merge_pred_buf_idx_array[i] !=
pau1_final_pred_buf_id[MERGE_DERIVED][0]))
{
pu1_pred_dst =
(UWORD8 *)ppv_pred_buf_list[pu1_merge_pred_buf_idx_array[i]] +
i4_buf_offset;
i1_retval = pu1_merge_pred_buf_idx_array[i];
break;
}
}
pu1_pred_src =
(UWORD8 *)ppv_pred_buf_list[pau1_final_pred_buf_id[MERGE_DERIVED][1]] +
i4_buf_offset;
pf_copy_2d(
pu1_pred_dst,
i4_stride,
pu1_pred_src,
i4_stride,
i4_part_wd_pu2 * u1_num_bytes_per_pel,
i4_part_ht_pu2);
/* Copy PU1 */
pu1_pred_src =
(UWORD8 *)ppv_pred_buf_list[pau1_final_pred_buf_id[ME_OR_SKIP_DERIVED][0]];
pu1_pred_dst = (UWORD8 *)ppv_pred_buf_list[i1_retval];
pf_copy_2d(
pu1_pred_dst,
i4_stride,
pu1_pred_src,
i4_stride,
i4_part_wd * u1_num_bytes_per_pel,
i4_part_ht);
ps_cand->pu1_pred_data = (UWORD8 *)ppv_pred_buf_list[i1_retval];
ps_cand->pu2_pred_data = (UWORD16 *)ppv_pred_buf_list[i1_retval];
ps_cand->i4_pred_data_stride = i4_pred_stride;
break;
}
}
}
}
return i1_retval;
}
static WORD8 ihevce_mixed_mode_cand_type0_pred_buffer_preparation(
void **ppv_pred_buf_list,
cu_inter_cand_t *ps_cand,
UWORD8 (*pau1_final_pred_buf_id)[MAX_NUM_INTER_PARTS],
UWORD8 *pu1_merge_pred_buf_idx_array,
UWORD8 u1_me_pred_buf_id,
UWORD8 u1_merge_pred_buf_id,
UWORD8 u1_mixed_tyep1_pred_buf_id,
WORD32 i4_pred_stride,
UWORD8 u1_cu_size,
UWORD8 u1_part_type,
UWORD8 u1_num_bytes_per_pel,
FT_COPY_2D *pf_copy_2d)
{
WORD32 i4_part_wd;
WORD32 i4_part_ht;
WORD32 i4_part_wd_pu2;
WORD32 i4_part_ht_pu2;
WORD32 i4_buf_offset;
UWORD8 *pu1_pred_src;
UWORD8 *pu1_pred_dst = NULL;
WORD8 i1_retval = pau1_final_pred_buf_id[ME_OR_SKIP_DERIVED][0];
WORD32 i4_stride = i4_pred_stride * u1_num_bytes_per_pel;
ASSERT(0 != u1_part_type);
i4_part_wd = (ps_cand->as_inter_pu[0].b4_wd + 1) << 2;
i4_part_ht = (ps_cand->as_inter_pu[0].b4_ht + 1) << 2;
i4_part_wd_pu2 = (ps_cand->as_inter_pu[1].b4_wd + 1) << 2;
i4_part_ht_pu2 = (ps_cand->as_inter_pu[1].b4_ht + 1) << 2;
i4_buf_offset = (i4_part_ht < u1_cu_size) * i4_part_ht * i4_pred_stride +
(i4_part_wd < u1_cu_size) * i4_part_wd;
i4_buf_offset *= u1_num_bytes_per_pel;
if(pau1_final_pred_buf_id[MIXED_MODE_TYPE0][0] == pau1_final_pred_buf_id[ME_OR_SKIP_DERIVED][0])
{
ps_cand->pu1_pred_data =
(UWORD8 *)ppv_pred_buf_list[pau1_final_pred_buf_id[ME_OR_SKIP_DERIVED][0]];
ps_cand->pu2_pred_data =
(UWORD16 *)ppv_pred_buf_list[pau1_final_pred_buf_id[ME_OR_SKIP_DERIVED][0]];
ps_cand->i4_pred_data_stride = i4_pred_stride;
i1_retval = pau1_final_pred_buf_id[ME_OR_SKIP_DERIVED][0];
}
else
{
UWORD8 u1_bitfield =
((u1_merge_pred_buf_id == UCHAR_MAX) << 2) | ((u1_me_pred_buf_id == UCHAR_MAX) << 1) |
(u1_mixed_tyep1_pred_buf_id != pau1_final_pred_buf_id[ME_OR_SKIP_DERIVED][0]);
switch(u1_bitfield)
{
case 7:
{
switch((PART_TYPE_T)u1_part_type)
{
case PRT_2NxN:
case PRT_Nx2N:
case PRT_2NxnU:
case PRT_nLx2N:
{
pu1_pred_src =
(UWORD8 *)ppv_pred_buf_list[pau1_final_pred_buf_id[MIXED_MODE_TYPE0][0]];
pu1_pred_dst =
(UWORD8 *)ppv_pred_buf_list[pau1_final_pred_buf_id[ME_OR_SKIP_DERIVED][1]];
i1_retval = pau1_final_pred_buf_id[MIXED_MODE_TYPE0][1];
break;
}
case PRT_nRx2N:
case PRT_2NxnD:
{
pu1_pred_src =
(UWORD8 *)ppv_pred_buf_list[pau1_final_pred_buf_id[ME_OR_SKIP_DERIVED][1]] +
i4_buf_offset;
pu1_pred_dst =
(UWORD8 *)ppv_pred_buf_list[pau1_final_pred_buf_id[MIXED_MODE_TYPE0][0]] +
i4_buf_offset;
i4_part_wd = i4_part_wd_pu2;
i4_part_ht = i4_part_ht_pu2;
i1_retval = pau1_final_pred_buf_id[MIXED_MODE_TYPE0][0];
break;
}
}
ps_cand->pu1_pred_data = (UWORD8 *)ppv_pred_buf_list[i1_retval];
ps_cand->pu2_pred_data = (UWORD16 *)ppv_pred_buf_list[i1_retval];
ps_cand->i4_pred_data_stride = i4_pred_stride;
pf_copy_2d(
pu1_pred_dst,
i4_stride,
pu1_pred_src,
i4_stride,
i4_part_wd * u1_num_bytes_per_pel,
i4_part_ht);
break;
}
case 6:
case 5:
case 4:
{
pu1_pred_src =
(UWORD8 *)ppv_pred_buf_list[pau1_final_pred_buf_id[ME_OR_SKIP_DERIVED][1]] +
i4_buf_offset;
pu1_pred_dst =
(UWORD8 *)ppv_pred_buf_list[pau1_final_pred_buf_id[MIXED_MODE_TYPE0][0]] +
i4_buf_offset;
i1_retval = pau1_final_pred_buf_id[MIXED_MODE_TYPE0][0];
ps_cand->pu1_pred_data = (UWORD8 *)ppv_pred_buf_list[i1_retval];
ps_cand->pu2_pred_data = (UWORD16 *)ppv_pred_buf_list[i1_retval];
ps_cand->i4_pred_data_stride = i4_pred_stride;
pf_copy_2d(
pu1_pred_dst,
i4_stride,
pu1_pred_src,
i4_stride,
i4_part_wd_pu2 * u1_num_bytes_per_pel,
i4_part_ht_pu2);
break;
}
case 3:
{
pu1_pred_src = (UWORD8 *)ppv_pred_buf_list[pau1_final_pred_buf_id[MIXED_MODE_TYPE0][0]];
pu1_pred_dst =
(UWORD8 *)ppv_pred_buf_list[pau1_final_pred_buf_id[ME_OR_SKIP_DERIVED][1]];
i1_retval = pau1_final_pred_buf_id[ME_OR_SKIP_DERIVED][1];
ps_cand->pu1_pred_data = (UWORD8 *)ppv_pred_buf_list[i1_retval];
ps_cand->pu2_pred_data = (UWORD16 *)ppv_pred_buf_list[i1_retval];
ps_cand->i4_pred_data_stride = i4_pred_stride;
pf_copy_2d(
pu1_pred_dst,
i4_stride,
pu1_pred_src,
i4_stride,
i4_part_wd * u1_num_bytes_per_pel,
i4_part_ht);
break;
}
case 2:
case 1:
case 0:
{
if((u1_merge_pred_buf_id == pau1_final_pred_buf_id[MERGE_DERIVED][1]) &&
(u1_merge_pred_buf_id != pau1_final_pred_buf_id[MERGE_DERIVED][0]))
{
pu1_pred_src =
(UWORD8 *)ppv_pred_buf_list[pau1_final_pred_buf_id[ME_OR_SKIP_DERIVED][1]] +
i4_buf_offset;
pu1_pred_dst =
(UWORD8 *)ppv_pred_buf_list[pau1_final_pred_buf_id[MERGE_DERIVED][0]] +
i4_buf_offset;
i1_retval = pau1_final_pred_buf_id[MERGE_DERIVED][0];
ps_cand->pu1_pred_data = (UWORD8 *)ppv_pred_buf_list[i1_retval];
ps_cand->pu2_pred_data = (UWORD16 *)ppv_pred_buf_list[i1_retval];
ps_cand->i4_pred_data_stride = i4_pred_stride;
pf_copy_2d(
pu1_pred_dst,
i4_stride,
pu1_pred_src,
i4_stride,
i4_part_wd_pu2 * u1_num_bytes_per_pel,
i4_part_ht_pu2);
}
else
{
UWORD8 i;
for(i = 0; i < 3; i++)
{
if((pu1_merge_pred_buf_idx_array[i] != u1_merge_pred_buf_id) &&
(pu1_merge_pred_buf_idx_array[i] != u1_mixed_tyep1_pred_buf_id))
{
pu1_pred_dst =
(UWORD8 *)ppv_pred_buf_list[pu1_merge_pred_buf_idx_array[i]] +
i4_buf_offset;
i1_retval = pu1_merge_pred_buf_idx_array[i];
break;
}
}
pu1_pred_src =
(UWORD8 *)ppv_pred_buf_list[pau1_final_pred_buf_id[ME_OR_SKIP_DERIVED][1]] +
i4_buf_offset;
pf_copy_2d(
pu1_pred_dst,
i4_stride,
pu1_pred_src,
i4_stride,
i4_part_wd_pu2 * u1_num_bytes_per_pel,
i4_part_ht_pu2);
/* Copy PU1 */
pu1_pred_src =
(UWORD8 *)ppv_pred_buf_list[pau1_final_pred_buf_id[MERGE_DERIVED][0]];
pu1_pred_dst = (UWORD8 *)ppv_pred_buf_list[i1_retval];
pf_copy_2d(
pu1_pred_dst,
i4_stride,
pu1_pred_src,
i4_stride,
i4_part_wd * u1_num_bytes_per_pel,
i4_part_ht);
ps_cand->pu1_pred_data = (UWORD8 *)ppv_pred_buf_list[i1_retval];
ps_cand->pu2_pred_data = (UWORD16 *)ppv_pred_buf_list[i1_retval];
ps_cand->i4_pred_data_stride = i4_pred_stride;
break;
}
}
}
}
return i1_retval;
}
static UWORD8 ihevce_find_idx_of_worst_cost(UWORD32 *pu4_cost_array, UWORD8 u1_array_size)
{
WORD32 i;
UWORD8 u1_worst_cost_idx = 0;
for(i = 1; i < u1_array_size; i++)
{
if(pu4_cost_array[i] > pu4_cost_array[u1_worst_cost_idx])
{
u1_worst_cost_idx = i;
}
}
return u1_worst_cost_idx;
}
static void ihevce_free_unused_buf_indices(
UWORD32 *pu4_pred_buf_usage_indicator,
UWORD8 *pu1_merge_pred_buf_idx_array,
UWORD8 *pu1_buf_id_in_use,
UWORD8 *pu1_buf_id_to_free,
UWORD8 u1_me_buf_id,
UWORD8 u1_num_available_cands,
UWORD8 u1_num_bufs_to_free,
UWORD8 u1_eval_merge,
UWORD8 u1_eval_skip,
UWORD8 u1_part_type)
{
UWORD8 i;
if(u1_eval_skip)
{
if(pu1_buf_id_in_use[ME_OR_SKIP_DERIVED] == pu1_merge_pred_buf_idx_array[0])
{
ihevce_set_pred_buf_as_free(
pu4_pred_buf_usage_indicator, pu1_merge_pred_buf_idx_array[1]);
}
else if(pu1_buf_id_in_use[ME_OR_SKIP_DERIVED] == pu1_merge_pred_buf_idx_array[1])
{
ihevce_set_pred_buf_as_free(
pu4_pred_buf_usage_indicator, pu1_merge_pred_buf_idx_array[0]);
}
else
{
ihevce_set_pred_buf_as_free(
pu4_pred_buf_usage_indicator, pu1_merge_pred_buf_idx_array[0]);
ihevce_set_pred_buf_as_free(
pu4_pred_buf_usage_indicator, pu1_merge_pred_buf_idx_array[1]);
}
for(i = 0; i < u1_num_bufs_to_free; i++)
{
if(pu1_buf_id_to_free[i] != u1_me_buf_id)
{
ihevce_set_pred_buf_as_free(pu4_pred_buf_usage_indicator, pu1_buf_id_to_free[i]);
}
}
}
else if((!u1_eval_merge) && (!u1_eval_skip) && (pu1_buf_id_in_use[ME_OR_SKIP_DERIVED] == UCHAR_MAX))
{
ihevce_set_pred_buf_as_free(pu4_pred_buf_usage_indicator, u1_me_buf_id);
for(i = 0; i < u1_num_bufs_to_free; i++)
{
if(pu1_buf_id_to_free[i] != u1_me_buf_id)
{
ihevce_set_pred_buf_as_free(pu4_pred_buf_usage_indicator, pu1_buf_id_to_free[i]);
}
}
}
else if((!u1_eval_merge) && (!u1_eval_skip) && (pu1_buf_id_in_use[ME_OR_SKIP_DERIVED] != UCHAR_MAX))
{
for(i = 0; i < u1_num_bufs_to_free; i++)
{
if(pu1_buf_id_to_free[i] != u1_me_buf_id)
{
ihevce_set_pred_buf_as_free(pu4_pred_buf_usage_indicator, pu1_buf_id_to_free[i]);
}
}
}
else if((u1_eval_merge) && (0 == u1_part_type))
{
/* ME pred buf */
COMPUTE_NUM_POSITIVE_REFERENCES_AND_FREE_IF_ZERO(
u1_me_buf_id,
pu1_buf_id_in_use,
pu1_buf_id_to_free,
4,
u1_num_bufs_to_free,
pu4_pred_buf_usage_indicator);
/* Merge pred buf 0 */
COMPUTE_NUM_POSITIVE_REFERENCES_AND_FREE_IF_ZERO(
pu1_merge_pred_buf_idx_array[0],
pu1_buf_id_in_use,
pu1_buf_id_to_free,
4,
u1_num_bufs_to_free,
pu4_pred_buf_usage_indicator);
/* Merge pred buf 1 */
COMPUTE_NUM_POSITIVE_REFERENCES_AND_FREE_IF_ZERO(
pu1_merge_pred_buf_idx_array[1],
pu1_buf_id_in_use,
pu1_buf_id_to_free,
4,
u1_num_bufs_to_free,
pu4_pred_buf_usage_indicator);
for(i = 0; i < u1_num_bufs_to_free; i++)
{
if((pu1_buf_id_to_free[i] != u1_me_buf_id) &&
(pu1_merge_pred_buf_idx_array[0] != pu1_buf_id_to_free[i]) &&
(pu1_merge_pred_buf_idx_array[1] != pu1_buf_id_to_free[i]))
{
ihevce_set_pred_buf_as_free(pu4_pred_buf_usage_indicator, pu1_buf_id_to_free[i]);
}
}
}
else if((u1_eval_merge) || (u1_eval_skip))
{
/* ME pred buf */
COMPUTE_NUM_POSITIVE_REFERENCES_AND_FREE_IF_ZERO(
u1_me_buf_id,
pu1_buf_id_in_use,
pu1_buf_id_to_free,
4,
u1_num_bufs_to_free,
pu4_pred_buf_usage_indicator);
/* Merge pred buf 0 */
COMPUTE_NUM_POSITIVE_REFERENCES_AND_FREE_IF_ZERO(
pu1_merge_pred_buf_idx_array[0],
pu1_buf_id_in_use,
pu1_buf_id_to_free,
4,
u1_num_bufs_to_free,
pu4_pred_buf_usage_indicator);
/* Merge pred buf 1 */
COMPUTE_NUM_POSITIVE_REFERENCES_AND_FREE_IF_ZERO(
pu1_merge_pred_buf_idx_array[1],
pu1_buf_id_in_use,
pu1_buf_id_to_free,
4,
u1_num_bufs_to_free,
pu4_pred_buf_usage_indicator);
/* Merge pred buf 2 */
COMPUTE_NUM_POSITIVE_REFERENCES_AND_FREE_IF_ZERO(
pu1_merge_pred_buf_idx_array[2],
pu1_buf_id_in_use,
pu1_buf_id_to_free,
4,
u1_num_bufs_to_free,
pu4_pred_buf_usage_indicator);
for(i = 0; i < u1_num_bufs_to_free; i++)
{
if((pu1_buf_id_to_free[i] != u1_me_buf_id) &&
(pu1_merge_pred_buf_idx_array[0] != pu1_buf_id_to_free[i]) &&
(pu1_merge_pred_buf_idx_array[1] != pu1_buf_id_to_free[i]))
{
ihevce_set_pred_buf_as_free(pu4_pred_buf_usage_indicator, pu1_buf_id_to_free[i]);
}
}
}
}
static UWORD8 ihevce_check_if_buf_can_be_freed(
UWORD8 *pu1_pred_id_of_winners,
UWORD8 u1_idx_of_worst_cost_in_pred_buf_array,
UWORD8 u1_num_cands_previously_added)
{
UWORD8 i;
UWORD8 u1_num_trysts = 0;
for(i = 0; i < u1_num_cands_previously_added; i++)
{
if(u1_idx_of_worst_cost_in_pred_buf_array == pu1_pred_id_of_winners[i])
{
u1_num_trysts++;
if(u1_num_trysts > 1)
{
return 0;
}
}
}
ASSERT(u1_num_trysts > 0);
return 1;
}
static void ihevce_get_worst_costs_and_indices(
UWORD32 *pu4_cost_src,
UWORD32 *pu4_cost_dst,
UWORD8 *pu1_worst_dst_cand_idx,
UWORD8 u1_src_array_length,
UWORD8 u1_num_cands_to_pick,
UWORD8 u1_worst_cost_idx_in_dst_array)
{
WORD32 i;
pu4_cost_dst[0] = pu4_cost_src[u1_worst_cost_idx_in_dst_array];
pu4_cost_src[u1_worst_cost_idx_in_dst_array] = 0;
pu1_worst_dst_cand_idx[0] = u1_worst_cost_idx_in_dst_array;
for(i = 1; i < u1_num_cands_to_pick; i++)
{
pu1_worst_dst_cand_idx[i] =
ihevce_find_idx_of_worst_cost(pu4_cost_src, u1_src_array_length);
pu4_cost_dst[i] = pu4_cost_src[pu1_worst_dst_cand_idx[i]];
pu4_cost_src[pu1_worst_dst_cand_idx[i]] = 0;
}
for(i = 0; i < u1_num_cands_to_pick; i++)
{
pu4_cost_src[pu1_worst_dst_cand_idx[i]] = pu4_cost_dst[i];
}
}
static UWORD8 ihevce_select_cands_to_replace_previous_worst(
UWORD32 *pu4_cost_src,
UWORD32 *pu4_cost_dst,
INTER_CANDIDATE_ID_T *pe_cand_id,
UWORD8 *pu1_cand_idx_in_dst_array,
UWORD8 *pu1_buf_id_to_free,
UWORD8 *pu1_pred_id_of_winners,
UWORD8 *pu1_num_bufs_to_free,
WORD32 i4_max_num_inter_rdopt_cands,
UWORD8 u1_num_cands_previously_added,
UWORD8 u1_num_available_cands,
UWORD8 u1_worst_cost_idx_in_dst_array)
{
WORD32 i, j, k;
UWORD32 au4_worst_dst_costs[4];
UWORD8 au1_worst_dst_cand_idx[4];
INTER_CANDIDATE_ID_T ae_default_cand_id[4] = {
ME_OR_SKIP_DERIVED, MERGE_DERIVED, MIXED_MODE_TYPE1, MIXED_MODE_TYPE0
};
UWORD8 u1_num_cands_to_add_wo_comparisons =
i4_max_num_inter_rdopt_cands - u1_num_cands_previously_added;
UWORD8 u1_num_cands_to_add_after_comparisons =
u1_num_available_cands - u1_num_cands_to_add_wo_comparisons;
UWORD8 u1_num_cands_to_add = 0;
UWORD8 au1_valid_src_cands[4] = { 0, 0, 0, 0 };
ASSERT(u1_num_cands_to_add_after_comparisons >= 0);
/* Sorting src costs */
SORT_PRIMARY_INTTYPE_ARRAY_AND_REORDER_GENERIC_COMPANION_ARRAY(
pu4_cost_src, pe_cand_id, u1_num_available_cands, INTER_CANDIDATE_ID_T);
for(i = 0; i < u1_num_cands_to_add_wo_comparisons; i++)
{
pu1_cand_idx_in_dst_array[u1_num_cands_to_add++] = u1_num_cands_previously_added + i;
au1_valid_src_cands[pe_cand_id[i]] = 1;
}
if(u1_num_cands_previously_added)
{
WORD8 i1_last_index = 0;
ihevce_get_worst_costs_and_indices(
pu4_cost_dst,
au4_worst_dst_costs,
au1_worst_dst_cand_idx,
u1_num_cands_previously_added,
u1_num_cands_to_add_after_comparisons,
u1_worst_cost_idx_in_dst_array);
for(i = u1_num_available_cands - 1; i >= u1_num_cands_to_add_wo_comparisons; i--)
{
for(j = u1_num_cands_to_add_after_comparisons - 1; j >= i1_last_index; j--)
{
if((pu4_cost_src[i] < au4_worst_dst_costs[j]))
{
if((i - u1_num_cands_to_add_wo_comparisons) <= j)
{
for(k = 0; k <= (i - u1_num_cands_to_add_wo_comparisons); k++)
{
pu1_cand_idx_in_dst_array[u1_num_cands_to_add++] =
au1_worst_dst_cand_idx[k];
au1_valid_src_cands[pe_cand_id[u1_num_cands_to_add_wo_comparisons + k]] =
1;
if(1 == ihevce_check_if_buf_can_be_freed(
pu1_pred_id_of_winners,
pu1_pred_id_of_winners[au1_worst_dst_cand_idx[k]],
u1_num_cands_previously_added))
{
pu1_buf_id_to_free[(*pu1_num_bufs_to_free)++] =
pu1_pred_id_of_winners[au1_worst_dst_cand_idx[k]];
}
else
{
pu1_pred_id_of_winners[au1_worst_dst_cand_idx[k]] = UCHAR_MAX;
}
}
i1_last_index = -1;
}
else
{
i1_last_index = j;
}
break;
}
}
if(-1 == i1_last_index)
{
break;
}
}
}
for(i = 0, j = 0; i < u1_num_available_cands; i++)
{
if(au1_valid_src_cands[ae_default_cand_id[i]])
{
pe_cand_id[j++] = ae_default_cand_id[i];
}
}
return u1_num_cands_to_add;
}
static UWORD8 ihevce_merge_cands_with_existing_best(
inter_cu_mode_info_t *ps_mode_info,
cu_inter_cand_t **pps_cand_src,
pu_mv_t (*pas_mvp_winner)[NUM_INTER_PU_PARTS],
UWORD32 (*pau4_cost)[MAX_NUM_INTER_PARTS],
void **ppv_pred_buf_list,
UWORD8 (*pau1_final_pred_buf_id)[MAX_NUM_INTER_PARTS],
UWORD32 *pu4_pred_buf_usage_indicator,
UWORD8 *pu1_num_merge_cands,
UWORD8 *pu1_num_skip_cands,
UWORD8 *pu1_num_mixed_mode_type0_cands,
UWORD8 *pu1_num_mixed_mode_type1_cands,
UWORD8 *pu1_merge_pred_buf_idx_array,
FT_COPY_2D *pf_copy_2d,
WORD32 i4_pred_stride,
WORD32 i4_max_num_inter_rdopt_cands,
UWORD8 u1_cu_size,
UWORD8 u1_part_type,
UWORD8 u1_eval_merge,
UWORD8 u1_eval_skip,
UWORD8 u1_num_bytes_per_pel)
{
UWORD32 au4_cost_src[4];
WORD32 i;
WORD32 u1_num_available_cands;
UWORD8 au1_buf_id_in_use[4];
UWORD8 au1_buf_id_to_free[4];
UWORD8 au1_cand_idx_in_dst_array[4];
INTER_CANDIDATE_ID_T ae_cand_id[4] = {
ME_OR_SKIP_DERIVED, MERGE_DERIVED, MIXED_MODE_TYPE1, MIXED_MODE_TYPE0
};
cu_inter_cand_t **pps_cand_dst = ps_mode_info->aps_cu_data;
UWORD8 u1_num_cands_previously_added = ps_mode_info->u1_num_inter_cands;
UWORD8 u1_worst_cost_idx = ps_mode_info->u1_idx_of_worst_cost_in_cost_array;
UWORD8 u1_idx_of_worst_cost_in_pred_buf_array =
ps_mode_info->u1_idx_of_worst_cost_in_pred_buf_array;
UWORD32 *pu4_cost_dst = ps_mode_info->au4_cost;
UWORD8 *pu1_pred_id_of_winners = ps_mode_info->au1_pred_buf_idx;
UWORD8 u1_num_bufs_to_free = 0;
UWORD8 u1_skip_or_merge_cand_is_valid = 0;
UWORD8 u1_num_invalid_cands = 0;
memset(au1_buf_id_in_use, UCHAR_MAX, sizeof(au1_buf_id_in_use));
u1_num_available_cands = (u1_eval_merge) ? 2 + ((u1_part_type != 0) + 1) : 1;
for(i = 0; i < u1_num_available_cands; i++)
{
WORD32 i4_idx = i - u1_num_invalid_cands;
if(u1_part_type == 0)
{
au4_cost_src[i4_idx] = pau4_cost[ae_cand_id[i4_idx]][0];
}
else
{
au4_cost_src[i4_idx] =
pau4_cost[ae_cand_id[i4_idx]][0] + pau4_cost[ae_cand_id[i4_idx]][1];
}
if(au4_cost_src[i4_idx] >= INT_MAX)
{
memmove(
&ae_cand_id[i4_idx],
&ae_cand_id[i4_idx + 1],
sizeof(INTER_CANDIDATE_ID_T) * (u1_num_available_cands - i - 1));
u1_num_invalid_cands++;
}
}
u1_num_available_cands -= u1_num_invalid_cands;
if((u1_num_cands_previously_added + u1_num_available_cands) > i4_max_num_inter_rdopt_cands)
{
u1_num_available_cands = ihevce_select_cands_to_replace_previous_worst(
au4_cost_src,
pu4_cost_dst,
ae_cand_id,
au1_cand_idx_in_dst_array,
au1_buf_id_to_free,
pu1_pred_id_of_winners,
&u1_num_bufs_to_free,
i4_max_num_inter_rdopt_cands,
u1_num_cands_previously_added,
u1_num_available_cands,
u1_worst_cost_idx);
}
else
{
for(i = 0; i < u1_num_available_cands; i++)
{
au1_cand_idx_in_dst_array[i] = u1_num_cands_previously_added + i;
}
}
for(i = 0; i < u1_num_available_cands; i++)
{
UWORD8 u1_dst_array_idx = au1_cand_idx_in_dst_array[i];
if(u1_part_type == 0)
{
au4_cost_src[i] = pau4_cost[ae_cand_id[i]][0];
}
else
{
au4_cost_src[i] = pau4_cost[ae_cand_id[i]][0] + pau4_cost[ae_cand_id[i]][1];
}
pps_cand_dst[u1_dst_array_idx] = pps_cand_src[ae_cand_id[i]];
/* Adding a skip candidate identical to the merge winner */
if((u1_eval_merge) && (0 == u1_part_type) && (MIXED_MODE_TYPE1 == ae_cand_id[i]))
{
(*pu1_num_skip_cands)++;
pu4_cost_dst[u1_dst_array_idx] = au4_cost_src[i];
if(u1_num_cands_previously_added >= i4_max_num_inter_rdopt_cands)
{
u1_worst_cost_idx =
ihevce_find_idx_of_worst_cost(pu4_cost_dst, u1_num_cands_previously_added);
u1_idx_of_worst_cost_in_pred_buf_array = pu1_pred_id_of_winners[u1_worst_cost_idx];
}
else
{
u1_num_cands_previously_added++;
}
if(u1_skip_or_merge_cand_is_valid)
{
pps_cand_dst[u1_dst_array_idx]->pu1_pred_data =
(UWORD8 *)ppv_pred_buf_list[au1_buf_id_in_use[MERGE_DERIVED]];
pps_cand_dst[u1_dst_array_idx]->pu2_pred_data =
(UWORD16 *)ppv_pred_buf_list[au1_buf_id_in_use[MERGE_DERIVED]];
pps_cand_dst[u1_dst_array_idx]->i4_pred_data_stride = i4_pred_stride;
au1_buf_id_in_use[MIXED_MODE_TYPE1] = au1_buf_id_in_use[MERGE_DERIVED];
pu1_pred_id_of_winners[u1_dst_array_idx] = au1_buf_id_in_use[MERGE_DERIVED];
}
else
{
u1_skip_or_merge_cand_is_valid = 1;
au1_buf_id_in_use[MIXED_MODE_TYPE1] = ihevce_merge_cand_pred_buffer_preparation(
ppv_pred_buf_list,
pps_cand_dst[u1_dst_array_idx],
pau1_final_pred_buf_id,
i4_pred_stride,
u1_cu_size,
u1_part_type,
u1_num_bytes_per_pel,
pf_copy_2d);
pu1_pred_id_of_winners[u1_dst_array_idx] = au1_buf_id_in_use[MIXED_MODE_TYPE1];
}
continue;
}
if(u1_num_cands_previously_added < i4_max_num_inter_rdopt_cands)
{
if(u1_num_cands_previously_added)
{
if(au4_cost_src[i] > pu4_cost_dst[u1_worst_cost_idx])
{
u1_worst_cost_idx = u1_num_cands_previously_added;
}
}
pu4_cost_dst[u1_dst_array_idx] = au4_cost_src[i];
u1_num_cands_previously_added++;
}
else
{
pu4_cost_dst[u1_dst_array_idx] = au4_cost_src[i];
u1_worst_cost_idx = ihevce_find_idx_of_worst_cost(
ps_mode_info->au4_cost, u1_num_cands_previously_added);
u1_idx_of_worst_cost_in_pred_buf_array = pu1_pred_id_of_winners[u1_worst_cost_idx];
}
switch(ae_cand_id[i])
{
case ME_OR_SKIP_DERIVED:
{
(*pu1_num_skip_cands) += u1_eval_skip;
pps_cand_dst[u1_dst_array_idx]->pu1_pred_data =
(UWORD8 *)ppv_pred_buf_list[pau1_final_pred_buf_id[ME_OR_SKIP_DERIVED][0]];
pps_cand_dst[u1_dst_array_idx]->pu2_pred_data =
(UWORD16 *)ppv_pred_buf_list[pau1_final_pred_buf_id[ME_OR_SKIP_DERIVED][0]];
pps_cand_dst[u1_dst_array_idx]->i4_pred_data_stride = i4_pred_stride;
if(u1_worst_cost_idx == u1_dst_array_idx)
{
u1_idx_of_worst_cost_in_pred_buf_array =
pau1_final_pred_buf_id[ME_OR_SKIP_DERIVED][0];
}
u1_skip_or_merge_cand_is_valid = u1_eval_skip;
au1_buf_id_in_use[ME_OR_SKIP_DERIVED] = pau1_final_pred_buf_id[ME_OR_SKIP_DERIVED][0];
pu1_pred_id_of_winners[u1_dst_array_idx] =
pau1_final_pred_buf_id[ME_OR_SKIP_DERIVED][0];
break;
}
case MERGE_DERIVED:
{
(*pu1_num_merge_cands)++;
au1_buf_id_in_use[MERGE_DERIVED] = ihevce_merge_cand_pred_buffer_preparation(
ppv_pred_buf_list,
pps_cand_dst[u1_dst_array_idx],
pau1_final_pred_buf_id,
i4_pred_stride,
u1_cu_size,
u1_part_type,
u1_num_bytes_per_pel,
pf_copy_2d
);
pu1_pred_id_of_winners[u1_dst_array_idx] = au1_buf_id_in_use[MERGE_DERIVED];
if(u1_worst_cost_idx == u1_dst_array_idx)
{
u1_idx_of_worst_cost_in_pred_buf_array = au1_buf_id_in_use[MERGE_DERIVED];
}
u1_skip_or_merge_cand_is_valid = 1;
break;
}
case MIXED_MODE_TYPE1:
{
(*pu1_num_mixed_mode_type1_cands)++;
au1_buf_id_in_use[MIXED_MODE_TYPE1] =
ihevce_mixed_mode_cand_type1_pred_buffer_preparation(
ppv_pred_buf_list,
pps_cand_dst[u1_dst_array_idx],
pau1_final_pred_buf_id,
pu1_merge_pred_buf_idx_array,
i4_pred_stride,
au1_buf_id_in_use[ME_OR_SKIP_DERIVED],
au1_buf_id_in_use[MERGE_DERIVED],
(u1_num_available_cands - i) > 1,
u1_cu_size,
u1_part_type,
u1_num_bytes_per_pel,
pf_copy_2d
);
pu1_pred_id_of_winners[u1_dst_array_idx] = au1_buf_id_in_use[MIXED_MODE_TYPE1];
if(u1_worst_cost_idx == u1_dst_array_idx)
{
u1_idx_of_worst_cost_in_pred_buf_array = au1_buf_id_in_use[MIXED_MODE_TYPE1];
}
break;
}
case MIXED_MODE_TYPE0:
{
(*pu1_num_mixed_mode_type0_cands)++;
au1_buf_id_in_use[MIXED_MODE_TYPE0] =
ihevce_mixed_mode_cand_type0_pred_buffer_preparation(
ppv_pred_buf_list,
pps_cand_dst[u1_dst_array_idx],
pau1_final_pred_buf_id,
pu1_merge_pred_buf_idx_array,
au1_buf_id_in_use[ME_OR_SKIP_DERIVED],
au1_buf_id_in_use[MERGE_DERIVED],
au1_buf_id_in_use[MIXED_MODE_TYPE1],
i4_pred_stride,
u1_cu_size,
u1_part_type,
u1_num_bytes_per_pel,
pf_copy_2d);
pu1_pred_id_of_winners[u1_dst_array_idx] = au1_buf_id_in_use[MIXED_MODE_TYPE0];
if(u1_worst_cost_idx == u1_dst_array_idx)
{
u1_idx_of_worst_cost_in_pred_buf_array = au1_buf_id_in_use[MIXED_MODE_TYPE0];
}
break;
}
}
}
ihevce_free_unused_buf_indices(
pu4_pred_buf_usage_indicator,
pu1_merge_pred_buf_idx_array,
au1_buf_id_in_use,
au1_buf_id_to_free,
pau1_final_pred_buf_id[ME_OR_SKIP_DERIVED][0],
u1_num_available_cands,
u1_num_bufs_to_free,
u1_eval_merge,
u1_eval_skip,
u1_part_type);
ps_mode_info->u1_idx_of_worst_cost_in_cost_array = u1_worst_cost_idx;
ps_mode_info->u1_num_inter_cands = u1_num_cands_previously_added;
ps_mode_info->u1_idx_of_worst_cost_in_pred_buf_array = u1_idx_of_worst_cost_in_pred_buf_array;
return u1_skip_or_merge_cand_is_valid;
}
static UWORD8 ihevce_prepare_cand_containers(
ihevce_inter_cand_sifter_prms_t *ps_ctxt,
cu_inter_cand_t **pps_cands,
UWORD8 *pu1_merge_pred_buf_idx_array,
UWORD8 *pu1_me_pred_buf_idx,
UWORD8 u1_part_type,
UWORD8 u1_me_cand_list_idx,
UWORD8 u1_eval_merge,
UWORD8 u1_eval_skip)
{
UWORD8 u1_num_bufs_currently_allocated;
WORD32 i4_pred_stride = ps_ctxt->ps_pred_buf_data->i4_pred_stride;
UWORD8 u1_cu_size = ps_ctxt->u1_cu_size;
UWORD8 u1_cu_pos_x = ps_ctxt->u1_cu_pos_x;
UWORD8 u1_cu_pos_y = ps_ctxt->u1_cu_pos_y;
void **ppv_pred_buf_list = ps_ctxt->ps_pred_buf_data->apv_inter_pred_data;
if(!u1_eval_merge)
{
if(u1_eval_skip)
{
u1_num_bufs_currently_allocated = ihevce_get_free_pred_buf_indices(
pu1_merge_pred_buf_idx_array, &ps_ctxt->ps_pred_buf_data->u4_is_buf_in_use, 2);
if(u1_num_bufs_currently_allocated < 2)
{
return 0;
}
pps_cands[ME_OR_SKIP_DERIVED] =
&ps_ctxt->ps_cu_inter_merge_skip->as_cu_inter_merge_skip_cand
[MAX_NUM_CU_MERGE_SKIP_CAND - 1 -
ps_ctxt->ps_cu_inter_merge_skip->u1_num_skip_cands];
pps_cands[ME_OR_SKIP_DERIVED]->b1_skip_flag = 1;
pps_cands[ME_OR_SKIP_DERIVED]->b1_eval_mark = 1;
pps_cands[ME_OR_SKIP_DERIVED]->b1_eval_tx_cusize = 1;
pps_cands[ME_OR_SKIP_DERIVED]->b1_eval_tx_cusize_by2 = 1;
pps_cands[ME_OR_SKIP_DERIVED]->b1_intra_has_won = 0;
pps_cands[ME_OR_SKIP_DERIVED]->b3_part_size = 0;
pps_cands[ME_OR_SKIP_DERIVED]->i4_pred_data_stride = i4_pred_stride;
pps_cands[ME_OR_SKIP_DERIVED]->as_inter_pu->b1_intra_flag = 0;
pps_cands[ME_OR_SKIP_DERIVED]->as_inter_pu->b1_merge_flag = 1;
pps_cands[ME_OR_SKIP_DERIVED]->as_inter_pu->b4_pos_x = u1_cu_pos_x >> 2;
pps_cands[ME_OR_SKIP_DERIVED]->as_inter_pu->b4_pos_y = u1_cu_pos_y >> 2;
pps_cands[ME_OR_SKIP_DERIVED]->as_inter_pu->b4_wd = (u1_cu_size >> 2) - 1;
pps_cands[ME_OR_SKIP_DERIVED]->as_inter_pu->b4_ht = (u1_cu_size >> 2) - 1;
pps_cands[MERGE_DERIVED] = pps_cands[ME_OR_SKIP_DERIVED];
}
else
{
u1_num_bufs_currently_allocated = ihevce_get_free_pred_buf_indices(
pu1_me_pred_buf_idx, &ps_ctxt->ps_pred_buf_data->u4_is_buf_in_use, 1);
if(u1_num_bufs_currently_allocated < 1)
{
return 0;
}
pps_cands[ME_OR_SKIP_DERIVED] = &ps_ctxt->ps_me_cands[u1_me_cand_list_idx];
pps_cands[ME_OR_SKIP_DERIVED]->i4_pred_data_stride = i4_pred_stride;
pps_cands[ME_OR_SKIP_DERIVED]->pu1_pred_data =
(UWORD8 *)ppv_pred_buf_list[*pu1_me_pred_buf_idx];
pps_cands[ME_OR_SKIP_DERIVED]->pu2_pred_data =
(UWORD16 *)ppv_pred_buf_list[*pu1_me_pred_buf_idx];
}
}
else
{
u1_num_bufs_currently_allocated = ihevce_get_free_pred_buf_indices(
pu1_me_pred_buf_idx, &ps_ctxt->ps_pred_buf_data->u4_is_buf_in_use, 1);
if(u1_num_bufs_currently_allocated < 1)
{
return 0;
}
pps_cands[ME_OR_SKIP_DERIVED] = &ps_ctxt->ps_me_cands[u1_me_cand_list_idx];
if(u1_part_type > 0)
{
u1_num_bufs_currently_allocated = ihevce_get_free_pred_buf_indices(
pu1_merge_pred_buf_idx_array, &ps_ctxt->ps_pred_buf_data->u4_is_buf_in_use, 3);
if(u1_num_bufs_currently_allocated < 3)
{
return 0;
}
pps_cands[MERGE_DERIVED] = &ps_ctxt->ps_cu_inter_merge_skip->as_cu_inter_merge_skip_cand
[ps_ctxt->ps_cu_inter_merge_skip->u1_num_merge_cands];
pps_cands[MIXED_MODE_TYPE0] =
&ps_ctxt->ps_mixed_modes_datastore
->as_cu_data[ps_ctxt->ps_mixed_modes_datastore->u1_num_mixed_mode_type0_cands];
pps_cands[MIXED_MODE_TYPE1] =
&ps_ctxt->ps_mixed_modes_datastore->as_cu_data
[MAX_NUM_MIXED_MODE_INTER_RDO_CANDS - 1 -
ps_ctxt->ps_mixed_modes_datastore->u1_num_mixed_mode_type1_cands];
*pps_cands[MERGE_DERIVED] = *pps_cands[ME_OR_SKIP_DERIVED];
*pps_cands[MIXED_MODE_TYPE0] = *pps_cands[ME_OR_SKIP_DERIVED];
*pps_cands[MIXED_MODE_TYPE1] = *pps_cands[ME_OR_SKIP_DERIVED];
}
else
{
u1_num_bufs_currently_allocated = ihevce_get_free_pred_buf_indices(
pu1_merge_pred_buf_idx_array, &ps_ctxt->ps_pred_buf_data->u4_is_buf_in_use, 2);
if(u1_num_bufs_currently_allocated < 2)
{
return 0;
}
pps_cands[MERGE_DERIVED] = &ps_ctxt->ps_cu_inter_merge_skip->as_cu_inter_merge_skip_cand
[ps_ctxt->ps_cu_inter_merge_skip->u1_num_merge_cands];
*pps_cands[MERGE_DERIVED] = *pps_cands[ME_OR_SKIP_DERIVED];
}
pps_cands[MERGE_DERIVED]->as_inter_pu[0].b1_merge_flag = 1;
pps_cands[MERGE_DERIVED]->as_inter_pu[1].b1_merge_flag = 1;
}
return u1_num_bufs_currently_allocated;
}
static __inline void ihevce_merge_prms_init(
merge_prms_t *ps_prms,
merge_cand_list_t *ps_list,
inter_pred_ctxt_t *ps_mc_ctxt,
mv_pred_ctxt_t *ps_mv_pred_ctxt,
PF_LUMA_INTER_PRED_PU pf_luma_inter_pred_pu,
PF_SAD_FXN_T pf_sad_fxn,
void **ppv_pred_buf_list,
ihevce_cmn_opt_func_t *ps_cmn_utils_optimised_function_list,
UWORD8 *pu1_merge_pred_buf_array,
UWORD8 (*pau1_best_pred_buf_id)[MAX_NUM_INTER_PARTS],
UWORD8 *pu1_is_top_used,
WORD32 (*pai4_noise_term)[MAX_NUM_INTER_PARTS],
UWORD32 (*pau4_pred_variance)[MAX_NUM_INTER_PARTS],
UWORD32 *pu4_src_variance,
WORD32 i4_alpha_stim_multiplier,
WORD32 i4_src_stride,
WORD32 i4_pred_stride,
WORD32 i4_lambda,
UWORD8 u1_is_cu_noisy,
UWORD8 u1_is_hbd,
UWORD8 u1_max_cands,
UWORD8 u1_merge_idx_cabac_model,
UWORD8 u1_use_merge_cand_from_top_row)
{
ps_prms->ps_list = ps_list;
ps_prms->ps_mc_ctxt = ps_mc_ctxt;
ps_prms->ps_mv_pred_ctxt = ps_mv_pred_ctxt;
ps_prms->pf_luma_inter_pred_pu = pf_luma_inter_pred_pu;
ps_prms->pf_sad_fxn = pf_sad_fxn;
ps_prms->ppv_pred_buf_list = ppv_pred_buf_list;
ps_prms->ps_cmn_utils_optimised_function_list = ps_cmn_utils_optimised_function_list;
ps_prms->pu1_merge_pred_buf_array = pu1_merge_pred_buf_array;
ps_prms->pau1_best_pred_buf_id = pau1_best_pred_buf_id;
ps_prms->pu1_is_top_used = pu1_is_top_used;
ps_prms->pai4_noise_term = pai4_noise_term;
ps_prms->pau4_pred_variance = pau4_pred_variance;
ps_prms->pu4_src_variance = pu4_src_variance;
ps_prms->i4_alpha_stim_multiplier = i4_alpha_stim_multiplier;
ps_prms->i4_src_stride = i4_src_stride;
ps_prms->i4_pred_stride = i4_pred_stride;
ps_prms->i4_lambda = i4_lambda;
ps_prms->u1_is_cu_noisy = u1_is_cu_noisy;
ps_prms->u1_is_hbd = u1_is_hbd;
ps_prms->u1_max_cands = u1_max_cands;
ps_prms->u1_merge_idx_cabac_model = u1_merge_idx_cabac_model;
ps_prms->u1_use_merge_cand_from_top_row = u1_use_merge_cand_from_top_row;
}
static UWORD8 ihevce_merge_candidate_seive(
nbr_avail_flags_t *ps_nbr,
merge_cand_list_t *ps_merge_cand,
UWORD8 *pu1_is_top_used,
UWORD8 u1_num_merge_cands,
UWORD8 u1_use_merge_cand_from_top_row)
{
if(!u1_use_merge_cand_from_top_row)
{
if(ps_nbr->u1_bot_lt_avail || ps_nbr->u1_left_avail)
{
return !pu1_is_top_used[0];
}
else
{
return 0;
}
}
else
{
return u1_num_merge_cands;
}
}
static UWORD8 ihevce_compute_pred_and_populate_modes(
ihevce_inter_cand_sifter_prms_t *ps_ctxt,
PF_SAD_FXN_T pf_sad_func,
UWORD32 *pu4_src_variance,
UWORD8 u1_part_type,
UWORD8 u1_me_cand_list_idx,
UWORD8 u1_eval_merge,
UWORD8 u1_eval_skip)
{
cu_inter_cand_t *aps_cands[4];
pu_mv_t as_mvp_winner[4][NUM_INTER_PU_PARTS];
merge_prms_t s_merge_prms;
merge_cand_list_t as_merge_cand[MAX_NUM_MERGE_CAND];
UWORD8 i, j;
UWORD32 au4_cost[4][NUM_INTER_PU_PARTS];
UWORD8 au1_final_pred_buf_id[4][NUM_INTER_PU_PARTS];
UWORD8 au1_merge_pred_buf_idx_array[3];
UWORD8 au1_is_top_used[MAX_NUM_MERGE_CAND];
UWORD8 u1_me_pred_buf_idx;
UWORD8 u1_num_bufs_currently_allocated;
WORD32 i4_mean;
UWORD32 au4_pred_variance[4][NUM_INTER_PU_PARTS];
WORD32 ai4_noise_term[4][NUM_INTER_PU_PARTS];
UWORD8 u1_cu_pos_x = ps_ctxt->u1_cu_pos_x;
UWORD8 u1_cu_pos_y = ps_ctxt->u1_cu_pos_y;
inter_cu_mode_info_t *ps_cu_mode_info = ps_ctxt->ps_inter_cu_mode_info;
inter_pred_ctxt_t *ps_mc_ctxt = ps_ctxt->ps_mc_ctxt;
nbr_4x4_t *ps_cu_nbr_buf = ps_ctxt->aps_cu_nbr_buf[0];
nbr_4x4_t *ps_pu_left_nbr = ps_ctxt->ps_left_nbr_4x4;
nbr_4x4_t *ps_pu_top_nbr = ps_ctxt->ps_top_nbr_4x4;
nbr_4x4_t *ps_pu_topleft_nbr = ps_ctxt->ps_topleft_nbr_4x4;
ihevce_inter_pred_buf_data_t *ps_pred_buf_info = ps_ctxt->ps_pred_buf_data;
mv_pred_ctxt_t *ps_mv_pred_ctxt = ps_ctxt->ps_mv_pred_ctxt;
PF_LUMA_INTER_PRED_PU pf_luma_inter_pred_pu = ps_ctxt->pf_luma_inter_pred_pu;
void *pv_src = ps_ctxt->pv_src;
WORD32 i4_src_stride = ps_ctxt->i4_src_strd;
WORD32 i4_pred_stride = ps_ctxt->ps_pred_buf_data->i4_pred_stride;
UWORD8 u1_num_parts = (u1_part_type != PRT_2Nx2N) + 1;
UWORD8 u1_num_bytes_per_pel = ps_ctxt->u1_is_hbd + 1;
void **ppv_pred_buf_list = ps_ctxt->ps_pred_buf_data->apv_inter_pred_data;
UWORD8 u1_cu_size = ps_ctxt->u1_cu_size;
WORD32 i4_nbr_4x4_left_stride = ps_ctxt->i4_nbr_4x4_left_strd;
UWORD8 *pu1_ctb_nbr_map = ps_ctxt->pu1_ctb_nbr_map;
WORD32 i4_nbr_map_stride = ps_ctxt->i4_ctb_nbr_map_stride;
UWORD8 u1_max_merge_candidates = ps_ctxt->u1_max_merge_candidates;
WORD32 i4_max_num_inter_rdopt_cands = ps_ctxt->i4_max_num_inter_rdopt_cands;
WORD32 i4_pred_buf_offset = 0;
WORD32 i4_src_buf_offset = 0;
UWORD8 u1_single_mcl_flag =
((8 == u1_cu_size) && (ps_mv_pred_ctxt->i4_log2_parallel_merge_level_minus2 > 0));
UWORD8 u1_skip_or_merge_cand_is_valid = 0;
WORD32 i4_lambda_qf = ps_ctxt->i4_lambda_qf;
UWORD8 u1_is_cu_noisy = ps_ctxt->u1_is_cu_noisy;
ASSERT(0 == (u1_eval_skip && u1_eval_merge));
ASSERT(u1_me_cand_list_idx < ps_ctxt->u1_num_me_cands);
/*
Algorithm -
1. Determine pred and satd for ME cand.
2. Determine merge winner for PU1.
3. Determine pred and satd for mixed_type0 cand.
4. Determine merge winner for PU2 and hence derive pred and satd for merge cand.
5. Determine merge winner for PU2 assuming ME cand as PU1 winner and hence derive
pred and satd for mixed_type1 cand.
6. Sort the 4 preceding costs and hence, the cand list.
7. Merge the sorted lists with the final cand list.
PS : 2 - 7 will be relevant only if u1_eval_merge = 1 and u1_eval_skip = 0
PPS : 1 will not be relevant if u1_eval_skip = 1
*/
/*
Explanatory notes -
1. Motion Vector Merge candidates and nbr's in all merge mode (RealD)
2. Motion Vector Merge candidates and nbr's in mixed mode (AltD)
*/
u1_num_bufs_currently_allocated = ihevce_prepare_cand_containers(
ps_ctxt,
aps_cands,
au1_merge_pred_buf_idx_array,
&u1_me_pred_buf_idx,
u1_part_type,
u1_me_cand_list_idx,
u1_eval_merge,
u1_eval_skip);
if(0 == u1_num_bufs_currently_allocated)
{
return 0;
}
if((u1_eval_merge) || (u1_eval_skip))
{
ihevce_merge_prms_init(
&s_merge_prms,
as_merge_cand,
ps_mc_ctxt,
ps_mv_pred_ctxt,
pf_luma_inter_pred_pu,
pf_sad_func,
ppv_pred_buf_list,
ps_ctxt->ps_cmn_utils_optimised_function_list,
au1_merge_pred_buf_idx_array,
au1_final_pred_buf_id,
au1_is_top_used,
ai4_noise_term,
au4_pred_variance,
pu4_src_variance,
ps_ctxt->i4_alpha_stim_multiplier,
i4_src_stride,
i4_pred_stride,
i4_lambda_qf,
u1_is_cu_noisy,
ps_ctxt->u1_is_hbd,
u1_max_merge_candidates,
ps_ctxt->u1_merge_idx_cabac_model,
ps_ctxt->u1_use_merge_cand_from_top_row);
}
for(i = 0; i < u1_num_parts; i++)
{
nbr_avail_flags_t s_nbr;
UWORD8 u1_part_wd;
UWORD8 u1_part_ht;
UWORD8 u1_pu_pos_x_4x4;
UWORD8 u1_pu_pos_y_4x4;
pu_t *ps_pu = &aps_cands[MERGE_DERIVED]->as_inter_pu[i];
PART_SIZE_E e_part_size = (PART_SIZE_E)aps_cands[ME_OR_SKIP_DERIVED]->b3_part_size;
void *pv_pu_src = (UWORD8 *)pv_src + i4_src_buf_offset;
UWORD8 u1_num_merge_cands = 0;
u1_part_wd = (aps_cands[0]->as_inter_pu[i].b4_wd + 1) << 2;
u1_part_ht = (aps_cands[0]->as_inter_pu[i].b4_ht + 1) << 2;
u1_pu_pos_x_4x4 = aps_cands[0]->as_inter_pu[i].b4_pos_x;
u1_pu_pos_y_4x4 = aps_cands[0]->as_inter_pu[i].b4_pos_y;
/* Inter cand pred and satd */
if(!u1_eval_skip)
{
void *pv_pu_pred = (UWORD8 *)ppv_pred_buf_list[u1_me_pred_buf_idx] + i4_pred_buf_offset;
if(ps_ctxt->u1_reuse_me_sad)
{
ihevce_compute_inter_pred_and_cost(
ps_mc_ctxt,
pf_luma_inter_pred_pu,
pf_sad_func,
&aps_cands[ME_OR_SKIP_DERIVED]->as_inter_pu[i],
pv_pu_src,
pv_pu_pred,
i4_src_stride,
i4_pred_stride,
0,
ps_ctxt->ps_cmn_utils_optimised_function_list);
au4_cost[ME_OR_SKIP_DERIVED][i] =
ps_ctxt->pai4_me_err_metric[u1_me_cand_list_idx][i];
}
else
{
au4_cost[ME_OR_SKIP_DERIVED][i] = ihevce_compute_inter_pred_and_cost(
ps_mc_ctxt,
pf_luma_inter_pred_pu,
pf_sad_func,
&aps_cands[ME_OR_SKIP_DERIVED]->as_inter_pu[i],
pv_pu_src,
pv_pu_pred,
i4_src_stride,
i4_pred_stride,
1,
ps_ctxt->ps_cmn_utils_optimised_function_list);
}
au1_final_pred_buf_id[ME_OR_SKIP_DERIVED][i] = u1_me_pred_buf_idx;
if(u1_is_cu_noisy && ps_ctxt->i4_alpha_stim_multiplier)
{
ihevce_calc_variance(
pv_pu_pred,
i4_pred_stride,
&i4_mean,
&au4_pred_variance[ME_OR_SKIP_DERIVED][i],
u1_part_ht,
u1_part_wd,
ps_ctxt->u1_is_hbd,
0);
ai4_noise_term[ME_OR_SKIP_DERIVED][i] = ihevce_compute_noise_term(
ps_ctxt->i4_alpha_stim_multiplier,
pu4_src_variance[i],
au4_pred_variance[ME_OR_SKIP_DERIVED][i]);
MULTIPLY_STIM_WITH_DISTORTION(
au4_cost[ME_OR_SKIP_DERIVED][i],
ai4_noise_term[ME_OR_SKIP_DERIVED][i],
STIM_Q_FORMAT,
ALPHA_Q_FORMAT);
}
}
if(u1_eval_skip || u1_eval_merge)
{
pu_t s_pu, *ps_pu_merge;
UWORD8 u1_is_any_top_available = 1;
UWORD8 u1_are_valid_merge_cands_available = 1;
/* get the neighbour availability flags */
if((u1_num_parts > 1) && u1_single_mcl_flag)
{ /* 8x8 SMPs take the 2Nx2N neighbours */
ihevce_get_only_nbr_flag(
&s_nbr,
pu1_ctb_nbr_map,
i4_nbr_map_stride,
aps_cands[0]->as_inter_pu[0].b4_pos_x,
aps_cands[0]->as_inter_pu[0].b4_pos_y,
u1_cu_size >> 2,
u1_cu_size >> 2);
/* Make the PU width and height as 8 */
memcpy(&s_pu, ps_pu, sizeof(pu_t));
s_pu.b4_pos_x = u1_cu_pos_x >> 2;
s_pu.b4_pos_y = u1_cu_pos_y >> 2;
s_pu.b4_wd = (u1_cu_size >> 2) - 1;
s_pu.b4_ht = (u1_cu_size >> 2) - 1;
/* Give the local PU structure to MV merge */
ps_pu_merge = &s_pu;
}
else
{
ihevce_get_only_nbr_flag(
&s_nbr,
pu1_ctb_nbr_map,
i4_nbr_map_stride,
u1_pu_pos_x_4x4,
u1_pu_pos_y_4x4,
u1_part_wd >> 2,
u1_part_ht >> 2);
u1_is_any_top_available = s_nbr.u1_top_avail || s_nbr.u1_top_rt_avail ||
s_nbr.u1_top_lt_avail;
if(!ps_ctxt->u1_use_merge_cand_from_top_row)
{
if(u1_is_any_top_available)
{
if(s_nbr.u1_left_avail || s_nbr.u1_bot_lt_avail)
{
s_nbr.u1_top_avail = 0;
s_nbr.u1_top_rt_avail = 0;
s_nbr.u1_top_lt_avail = 0;
}
else
{
u1_are_valid_merge_cands_available = 0;
}
}
}
/* Actual PU passed to MV merge */
ps_pu_merge = ps_pu;
}
if(u1_are_valid_merge_cands_available)
{
u1_num_merge_cands = ihevce_mv_pred_merge(
ps_mv_pred_ctxt,
ps_pu_top_nbr,
ps_pu_left_nbr,
ps_pu_topleft_nbr,
i4_nbr_4x4_left_stride,
&s_nbr,
NULL,
ps_pu_merge,
e_part_size,
i,
u1_single_mcl_flag,
as_merge_cand,
au1_is_top_used);
if(u1_num_merge_cands > u1_max_merge_candidates)
{
u1_num_merge_cands = u1_max_merge_candidates;
}
u1_num_merge_cands = ihevce_merge_candidate_seive(
&s_nbr,
as_merge_cand,
au1_is_top_used,
u1_num_merge_cands,
ps_ctxt->u1_use_merge_cand_from_top_row || !u1_is_any_top_available);
for(j = 0; j < u1_num_merge_cands; j++)
{
s_merge_prms.au1_valid_merge_indices[j] = j;
}
au4_cost[MERGE_DERIVED][i] = ihevce_determine_best_merge_pu(
&s_merge_prms,
&aps_cands[MERGE_DERIVED]->as_inter_pu[i],
&aps_cands[ME_OR_SKIP_DERIVED]->as_inter_pu[i],
pv_pu_src,
au4_cost[ME_OR_SKIP_DERIVED][i],
i4_pred_buf_offset,
u1_num_merge_cands,
i,
u1_eval_skip);
}
else
{
au4_cost[MERGE_DERIVED][i] = INT_MAX;
}
au4_cost[(i) ? MIXED_MODE_TYPE1 : MIXED_MODE_TYPE0][i] = au4_cost[MERGE_DERIVED][i];
if(u1_eval_skip)
{
/* This statement ensures that the skip candidate is always added */
au4_cost[ME_OR_SKIP_DERIVED][i] =
(au4_cost[MERGE_DERIVED][0] < INT_MAX) ? SKIP_MODE_COST : INT_MAX;
au1_final_pred_buf_id[ME_OR_SKIP_DERIVED][i] =
au1_final_pred_buf_id[MERGE_DERIVED][i];
}
else
{
au4_cost[ME_OR_SKIP_DERIVED][i] += ps_ctxt->pai4_mv_cost[u1_me_cand_list_idx][i];
au4_cost[(i) ? MIXED_MODE_TYPE0 : MIXED_MODE_TYPE1][i] =
au4_cost[ME_OR_SKIP_DERIVED][i];
}
au1_final_pred_buf_id[(i) ? MIXED_MODE_TYPE1 : MIXED_MODE_TYPE0][i] =
au1_final_pred_buf_id[MERGE_DERIVED][i];
au1_final_pred_buf_id[(i) ? MIXED_MODE_TYPE0 : MIXED_MODE_TYPE1][i] =
au1_final_pred_buf_id[ME_OR_SKIP_DERIVED][i];
}
else
{
au4_cost[ME_OR_SKIP_DERIVED][i] += ps_ctxt->pai4_mv_cost[u1_me_cand_list_idx][i];
}
if(!i && (u1_num_parts > 1) && u1_eval_merge)
{
ihevce_set_inter_nbr_map(
pu1_ctb_nbr_map,
i4_nbr_map_stride,
u1_pu_pos_x_4x4,
u1_pu_pos_y_4x4,
(u1_part_wd >> 2),
(u1_part_ht >> 2),
1);
ihevce_populate_nbr_4x4_with_pu_data(
ps_cu_nbr_buf, &aps_cands[ME_OR_SKIP_DERIVED]->as_inter_pu[i], u1_cu_size >> 2);
if(u1_part_wd < u1_cu_size)
{
i4_pred_buf_offset = i4_src_buf_offset = u1_part_wd;
if(!u1_single_mcl_flag) /* 8x8 SMPs take the 2Nx2N neighbours */
{
ps_cu_nbr_buf += (u1_part_wd >> 2);
ps_pu_left_nbr = ps_cu_nbr_buf - 1;
ps_pu_top_nbr += (u1_part_wd >> 2);
ps_pu_topleft_nbr = ps_pu_top_nbr - 1;
i4_nbr_4x4_left_stride = (u1_cu_size >> 2);
}
}
else if(u1_part_ht < u1_cu_size)
{
i4_pred_buf_offset = u1_part_ht * i4_pred_stride;
i4_src_buf_offset = u1_part_ht * i4_src_stride;
if(!u1_single_mcl_flag) /* 8x8 SMPs take the 2Nx2N neighbours */
{
ps_cu_nbr_buf += (u1_part_ht >> 2) * (u1_cu_size >> 2);
ps_pu_left_nbr += (u1_part_ht >> 2) * i4_nbr_4x4_left_stride;
ps_pu_top_nbr = ps_cu_nbr_buf - (u1_cu_size >> 2);
ps_pu_topleft_nbr = ps_pu_left_nbr - i4_nbr_4x4_left_stride;
}
}
i4_pred_buf_offset *= u1_num_bytes_per_pel;
i4_src_buf_offset *= u1_num_bytes_per_pel;
aps_cands[MIXED_MODE_TYPE0]->as_inter_pu[0] = aps_cands[MERGE_DERIVED]->as_inter_pu[0];
}
else if(!i && (u1_num_parts > 1) && (!u1_eval_merge))
{
if(u1_part_wd < u1_cu_size)
{
i4_pred_buf_offset = i4_src_buf_offset = u1_part_wd;
}
else if(u1_part_ht < u1_cu_size)
{
i4_pred_buf_offset = u1_part_ht * i4_pred_stride;
i4_src_buf_offset = u1_part_ht * i4_src_stride;
}
i4_pred_buf_offset *= u1_num_bytes_per_pel;
i4_src_buf_offset *= u1_num_bytes_per_pel;
}
else if(i && (u1_num_parts > 1) && u1_eval_merge)
{
aps_cands[MIXED_MODE_TYPE1]->as_inter_pu[1] = aps_cands[MERGE_DERIVED]->as_inter_pu[1];
}
}
/* Adding a skip candidate */
if((u1_eval_merge) && (0 == u1_part_type))
{
cu_inter_cand_t *ps_cand = &ps_ctxt->ps_cu_inter_merge_skip->as_cu_inter_merge_skip_cand
[MAX_NUM_CU_MERGE_SKIP_CAND - 1 -
ps_ctxt->ps_cu_inter_merge_skip->u1_num_skip_cands];
(*ps_cand) = (*aps_cands[MERGE_DERIVED]);
ps_cand->b1_skip_flag = 1;
aps_cands[MIXED_MODE_TYPE1] = ps_cand;
au4_cost[MIXED_MODE_TYPE1][0] = (au4_cost[MERGE_DERIVED][0] < INT_MAX) ? SKIP_MODE_COST
: INT_MAX;
}
/* Sort and populate */
u1_skip_or_merge_cand_is_valid = ihevce_merge_cands_with_existing_best(
ps_cu_mode_info,
aps_cands,
as_mvp_winner,
au4_cost,
ppv_pred_buf_list,
au1_final_pred_buf_id,
&ps_pred_buf_info->u4_is_buf_in_use,
&ps_ctxt->ps_cu_inter_merge_skip->u1_num_merge_cands,
&ps_ctxt->ps_cu_inter_merge_skip->u1_num_skip_cands,
&ps_ctxt->ps_mixed_modes_datastore->u1_num_mixed_mode_type0_cands,
&ps_ctxt->ps_mixed_modes_datastore->u1_num_mixed_mode_type1_cands,
au1_merge_pred_buf_idx_array,
ps_ctxt->ps_cmn_utils_optimised_function_list->pf_copy_2d,
i4_pred_stride,
i4_max_num_inter_rdopt_cands,
u1_cu_size,
u1_part_type,
u1_eval_merge,
u1_eval_skip,
u1_num_bytes_per_pel);
return u1_skip_or_merge_cand_is_valid;
}
static __inline void ihevce_redundant_candidate_pruner(inter_cu_mode_info_t *ps_inter_cu_mode_info)
{
WORD8 i, j;
WORD8 i1_num_merge_vs_mvds;
UWORD8 au1_redundant_cand_indices[MAX_NUM_INTER_RDO_CANDS] = { 0 };
for(i = 0; i < (ps_inter_cu_mode_info->u1_num_inter_cands - 1); i++)
{
if(au1_redundant_cand_indices[i] || ps_inter_cu_mode_info->aps_cu_data[i]->b1_skip_flag)
{
continue;
}
for(j = i + 1; j < ps_inter_cu_mode_info->u1_num_inter_cands; j++)
{
if(au1_redundant_cand_indices[j] || ps_inter_cu_mode_info->aps_cu_data[j]->b1_skip_flag)
{
continue;
}
i1_num_merge_vs_mvds = 0;
if(ps_inter_cu_mode_info->aps_cu_data[j]->b3_part_size ==
ps_inter_cu_mode_info->aps_cu_data[i]->b3_part_size)
{
if(ihevce_compare_pu_mv_t(
&ps_inter_cu_mode_info->aps_cu_data[i]->as_inter_pu->mv,
&ps_inter_cu_mode_info->aps_cu_data[j]->as_inter_pu->mv,
ps_inter_cu_mode_info->aps_cu_data[i]->as_inter_pu->b2_pred_mode,
ps_inter_cu_mode_info->aps_cu_data[j]->as_inter_pu->b2_pred_mode))
{
i1_num_merge_vs_mvds +=
ps_inter_cu_mode_info->aps_cu_data[i]->as_inter_pu->b1_merge_flag -
ps_inter_cu_mode_info->aps_cu_data[j]->as_inter_pu->b1_merge_flag;
if(ps_inter_cu_mode_info->aps_cu_data[i]->b3_part_size)
{
if(ihevce_compare_pu_mv_t(
&ps_inter_cu_mode_info->aps_cu_data[i]->as_inter_pu[1].mv,
&ps_inter_cu_mode_info->aps_cu_data[j]->as_inter_pu[1].mv,
ps_inter_cu_mode_info->aps_cu_data[i]->as_inter_pu[1].b2_pred_mode,
ps_inter_cu_mode_info->aps_cu_data[j]->as_inter_pu[1].b2_pred_mode))
{
i1_num_merge_vs_mvds +=
ps_inter_cu_mode_info->aps_cu_data[i]->as_inter_pu[1].b1_merge_flag -
ps_inter_cu_mode_info->aps_cu_data[j]->as_inter_pu[1].b1_merge_flag;
}
}
}
}
if(i1_num_merge_vs_mvds != 0)
{
au1_redundant_cand_indices[(i1_num_merge_vs_mvds > 0) ? j : i] = 1;
}
}
}
for(i = 0; i < ps_inter_cu_mode_info->u1_num_inter_cands; i++)
{
if(au1_redundant_cand_indices[i])
{
memmove(
&ps_inter_cu_mode_info->aps_cu_data[i],
&ps_inter_cu_mode_info->aps_cu_data[i + 1],
(ps_inter_cu_mode_info->u1_num_inter_cands - i - 1) *
sizeof(ps_inter_cu_mode_info->aps_cu_data[i]));
memmove(
&ps_inter_cu_mode_info->au4_cost[i],
&ps_inter_cu_mode_info->au4_cost[i + 1],
(ps_inter_cu_mode_info->u1_num_inter_cands - i - 1) *
sizeof(ps_inter_cu_mode_info->au4_cost[i]));
memmove(
&ps_inter_cu_mode_info->au1_pred_buf_idx[i],
&ps_inter_cu_mode_info->au1_pred_buf_idx[i + 1],
(ps_inter_cu_mode_info->u1_num_inter_cands - i - 1) *
sizeof(ps_inter_cu_mode_info->au1_pred_buf_idx[i]));
memmove(
&au1_redundant_cand_indices[i],
&au1_redundant_cand_indices[i + 1],
(ps_inter_cu_mode_info->u1_num_inter_cands - i - 1) *
sizeof(au1_redundant_cand_indices[i]));
ps_inter_cu_mode_info->u1_num_inter_cands--;
i--;
}
}
}
/*!
******************************************************************************
* \if Function name : ihevce_inter_cand_sifter \endif
*
* \brief
* Selects the best inter candidate modes amongst ME, merge,
* skip and mixed modes. Also computes corresponding preds
*
* \author
* Ittiam
*
*****************************************************************************
*/
void ihevce_inter_cand_sifter(ihevce_inter_cand_sifter_prms_t *ps_ctxt)
{
PF_SAD_FXN_T pf_sad_func;
UWORD8 au1_final_cand_idx[MAX_INTER_CU_CANDIDATES];
UWORD8 au1_part_types_evaluated[MAX_INTER_CU_CANDIDATES];
UWORD8 u1_num_unique_parts;
UWORD8 i, j;
UWORD32 au4_src_variance[NUM_INTER_PU_PARTS];
WORD32 i4_mean;
cu_inter_cand_t *ps_me_cands = ps_ctxt->ps_me_cands;
inter_cu_mode_info_t *ps_cu_mode_info = ps_ctxt->ps_inter_cu_mode_info;
UWORD8 u1_diff_skip_cand_flag = 1;
WORD8 i1_skip_cand_from_merge_idx = -1;
WORD8 i1_final_skip_cand_merge_idx = -1;
UWORD8 u1_max_num_part_types_to_select = MAX_INTER_CU_CANDIDATES;
UWORD8 u1_num_me_cands = ps_ctxt->u1_num_me_cands;
UWORD8 u1_num_parts_evaluated_for_merge = 0;
UWORD8 u1_is_cu_noisy = ps_ctxt->u1_is_cu_noisy;
if((ps_ctxt->u1_quality_preset >= IHEVCE_QUALITY_P3) && (ps_ctxt->i1_slice_type == BSLICE))
{
u1_max_num_part_types_to_select = 1;
}
{
pf_sad_func = (ps_ctxt->u1_use_satd_for_merge_eval) ? compute_satd_8bit
: ps_ctxt->pf_evalsad_pt_npu_mxn_8bit;
}
u1_num_unique_parts = ihevce_get_num_part_types_in_me_cand_list(
ps_me_cands,
au1_part_types_evaluated,
au1_final_cand_idx,
&u1_diff_skip_cand_flag,
&i1_skip_cand_from_merge_idx,
&i1_final_skip_cand_merge_idx,
u1_max_num_part_types_to_select,
u1_num_me_cands);
if((u1_num_me_cands + u1_diff_skip_cand_flag) && u1_is_cu_noisy &&
ps_ctxt->i4_alpha_stim_multiplier)
{
ihevce_calc_variance(
ps_ctxt->pv_src,
ps_ctxt->i4_src_strd,
&i4_mean,
&ps_cu_mode_info->u4_src_variance,
ps_ctxt->u1_cu_size,
ps_ctxt->u1_cu_size,
ps_ctxt->u1_is_hbd,
0);
}
if(DISABLE_SKIP_AND_MERGE_WHEN_NOISY && u1_is_cu_noisy)
{
u1_diff_skip_cand_flag = 0;
}
else if(!DISABLE_SKIP_AND_MERGE_WHEN_NOISY && u1_is_cu_noisy)
{
if(ps_ctxt->u1_cu_size > MAX_CU_SIZE_WHERE_MERGE_AND_SKIPS_ENABLED_AND_WHEN_NOISY)
{
u1_diff_skip_cand_flag = 0;
}
}
for(i = 0; i < u1_num_me_cands + u1_diff_skip_cand_flag; i++)
{
UWORD8 u1_part_type;
UWORD8 u1_eval_skip;
UWORD8 u1_eval_merge;
UWORD8 u1_valid_cand;
if(i == u1_num_me_cands)
{
u1_eval_skip = 1;
u1_eval_merge = 0;
u1_part_type = 0;
}
else
{
u1_eval_skip = 0;
u1_part_type = ps_me_cands[i].b3_part_size;
if(u1_num_parts_evaluated_for_merge >= u1_num_unique_parts)
{
u1_eval_merge = 0;
u1_num_parts_evaluated_for_merge = u1_num_unique_parts;
}
else
{
u1_eval_merge = (i == au1_final_cand_idx[u1_num_parts_evaluated_for_merge]);
}
for(j = 0; (j < u1_num_parts_evaluated_for_merge) && (u1_eval_merge); j++)
{
if(u1_part_type == au1_part_types_evaluated[j])
{
u1_eval_merge = 0;
break;
}
}
}
if(u1_is_cu_noisy && u1_part_type && ps_ctxt->i4_alpha_stim_multiplier)
{
void *pv_src = ps_ctxt->pv_src;
UWORD8 u1_pu_wd = (ps_me_cands[i].as_inter_pu[0].b4_wd + 1) << 2;
UWORD8 u1_pu_ht = (ps_me_cands[i].as_inter_pu[0].b4_ht + 1) << 2;
ihevce_calc_variance(
pv_src,
ps_ctxt->i4_src_strd,
&i4_mean,
&au4_src_variance[0],
u1_pu_ht,
u1_pu_wd,
ps_ctxt->u1_is_hbd,
0);
pv_src = (void *) (((UWORD8 *) pv_src) +
((ps_ctxt->u1_cu_size == u1_pu_wd) ? ps_ctxt->i4_src_strd * u1_pu_ht : u1_pu_wd)
* (ps_ctxt->u1_is_hbd + 1));
u1_pu_wd = (ps_me_cands[i].as_inter_pu[1].b4_wd + 1) << 2;
u1_pu_ht = (ps_me_cands[i].as_inter_pu[1].b4_ht + 1) << 2;
ihevce_calc_variance(
pv_src,
ps_ctxt->i4_src_strd,
&i4_mean,
&au4_src_variance[1],
u1_pu_ht,
u1_pu_wd,
ps_ctxt->u1_is_hbd,
0);
}
else if(u1_is_cu_noisy && !u1_part_type && ps_ctxt->i4_alpha_stim_multiplier)
{
au4_src_variance[0] = ps_cu_mode_info->u4_src_variance;
}
if(DISABLE_SKIP_AND_MERGE_WHEN_NOISY && u1_is_cu_noisy)
{
u1_eval_merge = 0;
}
else if(!DISABLE_SKIP_AND_MERGE_WHEN_NOISY && u1_is_cu_noisy)
{
if(ps_ctxt->u1_cu_size > MAX_CU_SIZE_WHERE_MERGE_AND_SKIPS_ENABLED_AND_WHEN_NOISY)
{
u1_eval_merge = 0;
}
}
u1_valid_cand = ihevce_compute_pred_and_populate_modes(
ps_ctxt,
pf_sad_func,
au4_src_variance,
u1_part_type,
MIN(i, (u1_num_me_cands - 1)),
u1_eval_merge,
u1_eval_skip);
u1_num_parts_evaluated_for_merge += u1_eval_merge;
/* set the neighbour map to 0 */
if(u1_part_type)
{
ihevce_set_nbr_map(
ps_ctxt->pu1_ctb_nbr_map,
ps_ctxt->i4_ctb_nbr_map_stride,
(ps_ctxt->u1_cu_pos_x >> 2),
(ps_ctxt->u1_cu_pos_y >> 2),
(ps_ctxt->u1_cu_size >> 2),
0);
}
}
ihevce_redundant_candidate_pruner(ps_ctxt->ps_inter_cu_mode_info);
}