2746 lines
93 KiB
C
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);
|
|
}
|