/****************************************************************************** * * 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_had_satd.c * * @brief * This file contains functions of Hadamard SAD and SATD * * @author * Ittiam * * List of Functions * <TODO: TO BE ADDED> * ****************************************************************************** */ /*****************************************************************************/ /* File Includes */ /*****************************************************************************/ /* System include files */ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <assert.h> #include <stdarg.h> #include <math.h> /* User include files */ #include "ihevc_typedefs.h" #include "itt_video_api.h" #include "ihevce_api.h" #include "rc_cntrl_param.h" #include "rc_frame_info_collector.h" #include "rc_look_ahead_params.h" #include "ihevc_defs.h" #include "ihevc_structs.h" #include "ihevc_platform_macros.h" #include "ihevc_deblk.h" #include "ihevc_itrans_recon.h" #include "ihevc_chroma_itrans_recon.h" #include "ihevc_chroma_intra_pred.h" #include "ihevc_intra_pred.h" #include "ihevc_inter_pred.h" #include "ihevc_mem_fns.h" #include "ihevc_padding.h" #include "ihevc_weighted_pred.h" #include "ihevc_sao.h" #include "ihevc_resi_trans.h" #include "ihevc_quant_iquant_ssd.h" #include "ihevc_cabac_tables.h" #include "ihevce_defs.h" #include "ihevce_lap_enc_structs.h" #include "ihevce_multi_thrd_structs.h" #include "ihevce_multi_thrd_funcs.h" #include "ihevce_me_common_defs.h" #include "ihevce_had_satd.h" #include "ihevce_error_codes.h" #include "ihevce_bitstream.h" #include "ihevce_cabac.h" #include "ihevce_rdoq_macros.h" #include "ihevce_function_selector.h" #include "ihevce_enc_structs.h" #include "ihevce_cmn_utils_instr_set_router.h" #include "hme_datatype.h" #include "hme_interface.h" #include "hme_common_defs.h" #include "hme_defs.h" /*****************************************************************************/ /* Function Definitions */ /*****************************************************************************/ static void ihevce_hadamard_4x4_8bit( UWORD8 *pu1_src, WORD32 src_strd, UWORD8 *pu1_pred, WORD32 pred_strd, WORD16 *pi2_dst, WORD32 dst_strd) { WORD32 k; WORD16 m[16]; /*===== hadamard horz transform =====*/ for(k = 0; k < 4; k++) { WORD32 r0, r1, r2, r3; WORD32 h0, h1, h2, h3; /* Compute the residue block */ r0 = pu1_src[0] - pu1_pred[0]; r1 = pu1_src[1] - pu1_pred[1]; r2 = pu1_src[2] - pu1_pred[2]; r3 = pu1_src[3] - pu1_pred[3]; h0 = r0 + r1; h1 = r0 - r1; h2 = r2 + r3; h3 = r2 - r3; m[k * 4 + 0] = h0 + h2; m[k * 4 + 1] = h1 + h3; m[k * 4 + 2] = h0 - h2; m[k * 4 + 3] = h1 - h3; pu1_pred += pred_strd; pu1_src += src_strd; } /*===== hadamard vert transform =====*/ for(k = 0; k < 4; k++) { WORD32 v0, v1, v2, v3; v0 = m[0 + k] + m[4 + k]; v1 = m[0 + k] - m[4 + k]; v2 = m[8 + k] + m[12 + k]; v3 = m[8 + k] - m[12 + k]; pi2_dst[0 * dst_strd + k] = v0 + v2; pi2_dst[1 * dst_strd + k] = v1 + v3; pi2_dst[2 * dst_strd + k] = v0 - v2; pi2_dst[3 * dst_strd + k] = v1 - v3; } } static void ihevce_hadamard_8x8_8bit( UWORD8 *pu1_src, WORD32 src_strd, UWORD8 *pu1_pred, WORD32 pred_strd, WORD16 *pi2_dst, WORD32 dst_strd) { WORD32 i; // y0 ihevce_hadamard_4x4_8bit(pu1_src, src_strd, pu1_pred, pred_strd, pi2_dst, dst_strd); // y1 ihevce_hadamard_4x4_8bit(pu1_src + 4, src_strd, pu1_pred + 4, pred_strd, pi2_dst + 4, dst_strd); // y2 ihevce_hadamard_4x4_8bit( pu1_src + 4 * src_strd, src_strd, pu1_pred + 4 * pred_strd, pred_strd, pi2_dst + (4 * dst_strd), dst_strd); // y3 ihevce_hadamard_4x4_8bit( pu1_src + 4 + 4 * src_strd, src_strd, pu1_pred + 4 + 4 * pred_strd, pred_strd, pi2_dst + (4 * dst_strd) + 4, dst_strd); /* Child HAD results combined as follows to get Parent result */ /* _ _ */ /* | (y0 + y1) + (y2 + y3) (y0 - y1) + (y2 - y3) | */ /* | (y0 + y1) - (y2 + y3) (y0 - y1) - (y2 - y3) | */ /* \- -/ */ for(i = 0; i < 16; i++) { WORD32 idx = (i >> 2) * dst_strd + (i % 4); WORD16 a0 = pi2_dst[idx]; WORD16 a1 = pi2_dst[4 + idx]; WORD16 a2 = pi2_dst[(4 * dst_strd) + idx]; WORD16 a3 = pi2_dst[(4 * dst_strd) + 4 + idx]; WORD16 b0 = (a0 + a1); WORD16 b1 = (a0 - a1); WORD16 b2 = (a2 + a3); WORD16 b3 = (a2 - a3); pi2_dst[idx] = b0 + b2; pi2_dst[4 + idx] = b1 + b3; pi2_dst[(4 * dst_strd) + idx] = b0 - b2; pi2_dst[(4 * dst_strd) + 4 + idx] = b1 - b3; } } static void ihevce_hadamard_16x16_8bit( UWORD8 *pu1_src, WORD32 src_strd, UWORD8 *pu1_pred, WORD32 pred_strd, WORD16 *pi2_dst, WORD32 dst_strd) { WORD32 i; // y0 ihevce_hadamard_8x8_8bit(pu1_src, src_strd, pu1_pred, pred_strd, pi2_dst, dst_strd); // y1 ihevce_hadamard_8x8_8bit(pu1_src + 8, src_strd, pu1_pred + 8, pred_strd, pi2_dst + 8, dst_strd); // y2 ihevce_hadamard_8x8_8bit( pu1_src + 8 * src_strd, src_strd, pu1_pred + 8 * pred_strd, pred_strd, pi2_dst + (8 * dst_strd), dst_strd); // y3 ihevce_hadamard_8x8_8bit( pu1_src + 8 + 8 * src_strd, src_strd, pu1_pred + 8 + 8 * pred_strd, pred_strd, pi2_dst + (8 * dst_strd) + 8, dst_strd); /* Child HAD results combined as follows to get Parent result */ /* _ _ */ /* | (y0 + y1) + (y2 + y3) (y0 - y1) + (y2 - y3) | */ /* | (y0 + y1) - (y2 + y3) (y0 - y1) - (y2 - y3) | */ /* \- -/ */ for(i = 0; i < 64; i++) { WORD32 idx = (i >> 3) * dst_strd + (i % 8); WORD16 a0 = pi2_dst[idx]; WORD16 a1 = pi2_dst[8 + idx]; WORD16 a2 = pi2_dst[(8 * dst_strd) + idx]; WORD16 a3 = pi2_dst[(8 * dst_strd) + 8 + idx]; WORD16 b0 = (a0 + a1) >> 1; WORD16 b1 = (a0 - a1) >> 1; WORD16 b2 = (a2 + a3) >> 1; WORD16 b3 = (a2 - a3) >> 1; pi2_dst[idx] = b0 + b2; pi2_dst[8 + idx] = b1 + b3; pi2_dst[(8 * dst_strd) + idx] = b0 - b2; pi2_dst[(8 * dst_strd) + 8 + idx] = b1 - b3; } } static void ihevce_hadamard_32x32_8bit( UWORD8 *pu1_src, WORD32 src_strd, UWORD8 *pu1_pred, WORD32 pred_strd, WORD16 *pi2_dst, WORD32 dst_strd) { WORD32 i; // y0 ihevce_hadamard_16x16_8bit(pu1_src, src_strd, pu1_pred, pred_strd, pi2_dst, dst_strd); // y1 ihevce_hadamard_16x16_8bit( pu1_src + 16, src_strd, pu1_pred + 16, pred_strd, pi2_dst + 16, dst_strd); // y2 ihevce_hadamard_16x16_8bit( pu1_src + 16 * src_strd, src_strd, pu1_pred + 16 * pred_strd, pred_strd, pi2_dst + (16 * dst_strd), dst_strd); // y3 ihevce_hadamard_16x16_8bit( pu1_src + 16 + 16 * src_strd, src_strd, pu1_pred + 16 + 16 * pred_strd, pred_strd, pi2_dst + (16 * dst_strd) + 16, dst_strd); /* Child HAD results combined as follows to get Parent result */ /* _ _ */ /* | (y0 + y1) + (y2 + y3) (y0 - y1) + (y2 - y3) | */ /* | (y0 + y1) - (y2 + y3) (y0 - y1) - (y2 - y3) | */ /* \- -/ */ for(i = 0; i < 256; i++) { WORD32 idx = (i >> 4) * dst_strd + (i % 16); WORD16 a0 = pi2_dst[idx] >> 2; WORD16 a1 = pi2_dst[16 + idx] >> 2; WORD16 a2 = pi2_dst[(16 * dst_strd) + idx] >> 2; WORD16 a3 = pi2_dst[(16 * dst_strd) + 16 + idx] >> 2; WORD16 b0 = (a0 + a1); WORD16 b1 = (a0 - a1); WORD16 b2 = (a2 + a3); WORD16 b3 = (a2 - a3); pi2_dst[idx] = b0 + b2; pi2_dst[16 + idx] = b1 + b3; pi2_dst[(16 * dst_strd) + idx] = b0 - b2; pi2_dst[(16 * dst_strd) + 16 + idx] = b1 - b3; } } /** ******************************************************************************* * * @brief * Compute Hadamard sad for 4x4 block with 8-bit input * * @par Description: * * @param[in] pu1_origin * UWORD8 pointer to the current block * * @param[in] src_strd * WORD32 Source stride * * @param[in] pu1_pred_buf * UWORD8 pointer to the prediction block * * @param[in] pred_strd * WORD32 Pred stride * * @param[in] pi2_dst * WORD16 pointer to the transform block * * @param[in] dst_strd * WORD32 Destination stride * * @param[in] size * WORD32 transform Block size * * @returns hadamard SAD * * @remarks * Not updating the transform destination now. Only returning the SATD * ******************************************************************************* */ UWORD32 ihevce_HAD_4x4_8bit( UWORD8 *pu1_origin, WORD32 src_strd, UWORD8 *pu1_pred_buf, WORD32 pred_strd, WORD16 *pi2_dst, WORD32 dst_strd) { WORD32 k; WORD16 v[16]; UWORD32 u4_sad = 0; (void)pi2_dst; (void)dst_strd; ihevce_hadamard_4x4_8bit(pu1_origin, src_strd, pu1_pred_buf, pred_strd, v, 4); for(k = 0; k < 16; ++k) u4_sad += abs(v[k]); u4_sad = ((u4_sad + 2) >> 2); return u4_sad; } /** ******************************************************************************* * * @brief * Computes Hadamard Sad for 8x8 block with 8-bit input * * @par Description: * * @param[in] pu1_origin * UWORD8 pointer to the current block * * @param[in] src_strd * WORD32 Source stride * * @param[in] pu1_pred_buf * UWORD8 pointer to the prediction block * * @param[in] pred_strd * WORD32 Pred stride * * @param[in] pi2_dst * WORD16 pointer to the transform block * * @param[in] dst_strd * WORD32 Destination stride * * @param[in] size * WORD32 transform Block size * * @returns Hadamard SAD * * @remarks * Not updating the transform destination now. Only returning the SATD * ******************************************************************************* */ UWORD32 ihevce_HAD_8x8_8bit( UWORD8 *pu1_origin, WORD32 src_strd, UWORD8 *pu1_pred_buf, WORD32 pred_strd, WORD16 *pi2_dst, WORD32 dst_strd) { WORD32 k; UWORD32 u4_sad = 0; WORD16 v[64]; (void)pi2_dst; (void)dst_strd; ihevce_hadamard_8x8_8bit(pu1_origin, src_strd, pu1_pred_buf, pred_strd, v, 8); for(k = 0; k < 64; ++k) u4_sad += abs(v[k]); u4_sad = ((u4_sad + 4) >> 3); return u4_sad; } /** ******************************************************************************* * * @brief * Compute dc suppressed hadamard sad for 8x8 block with 8-bit input * * @par Description: * * @param[in] pu1_origin * UWORD8 pointer to the current block * * @param[in] src_strd * WORD32 Source stride * * @param[in] pu1_pred_buf * UWORD8 pointer to the prediction block * * @param[in] pred_strd * WORD32 Pred stride * * @param[in] pi2_dst * WORD16 pointer to the transform block * * @param[in] dst_strd * WORD32 Destination stride * * @param[in] size * WORD32 transform Block size * * @returns Hadamard SAD with DC Suppressed * * @remarks * Not updating the transform destination now. Only returning the SATD * ******************************************************************************* */ UWORD32 ihevce_compute_ac_had_8x8_8bit( UWORD8 *pu1_origin, WORD32 src_strd, UWORD8 *pu1_pred_buf, WORD32 pred_strd, WORD16 *pi2_dst, WORD32 dst_strd) { WORD32 k; UWORD32 u4_sad = 0; WORD16 v[64]; (void)pi2_dst; (void)dst_strd; ihevce_hadamard_8x8_8bit(pu1_origin, src_strd, pu1_pred_buf, pred_strd, v, 8); v[0] = 0; for(k = 0; k < 64; ++k) u4_sad += abs(v[k]); u4_sad = ((u4_sad + 4) >> 3); return u4_sad; } /** ******************************************************************************* * * @brief * Computes Hadamard Sad for 16x16 block with 8-bit input * * @par Description: * * @param[in] pu1_origin * UWORD8 pointer to the current block * * @param[in] src_strd * WORD32 Source stride * * @param[in] pu1_pred_buf * UWORD8 pointer to the prediction block * * @param[in] pred_strd * WORD32 Pred stride * * @param[in] pi2_dst * WORD16 pointer to the transform block * * @param[in] dst_strd * WORD32 Destination stride * * @param[in] size * WORD32 transform Block size * * @returns Hadamard SAD * * @remarks * Not updating the transform destination now. Only returning the SATD * ******************************************************************************* */ UWORD32 ihevce_HAD_16x16_8bit( UWORD8 *pu1_origin, WORD32 src_strd, UWORD8 *pu1_pred_buf, WORD32 pred_strd, WORD16 *pi2_dst, WORD32 dst_strd) { WORD32 k; UWORD32 u4_sad = 0; WORD16 v[256]; (void)pi2_dst; (void)dst_strd; ihevce_hadamard_16x16_8bit(pu1_origin, src_strd, pu1_pred_buf, pred_strd, v, 16); for(k = 0; k < 256; ++k) u4_sad += abs(v[k]); u4_sad = ((u4_sad + 4) >> 3); return u4_sad; } /** ******************************************************************************* * * @brief * Computes Hadamard Sad for 32x32 block with 8-bit input * * @par Description: * * @param[in] pu1_origin * UWORD8 pointer to the current block * * @param[in] src_strd * WORD32 Source stride * * @param[in] pu1_pred_buf * UWORD8 pointer to the prediction block * * @param[in] pred_strd * WORD32 Pred stride * * @param[in] pi2_dst * WORD16 pointer to the transform block * * @param[in] dst_strd * WORD32 Destination stride * * @param[in] size * WORD32 transform Block size * * @returns Hadamard SAD * * @remarks * Not updating the transform destination now. Only returning the SATD * ******************************************************************************* */ UWORD32 ihevce_HAD_32x32_8bit( UWORD8 *pu1_origin, WORD32 src_strd, UWORD8 *pu1_pred_buf, WORD32 pred_strd, WORD16 *pi2_dst, WORD32 dst_strd) { WORD32 k; UWORD32 u4_sad = 0; WORD16 v[32 * 32]; (void)pi2_dst; (void)dst_strd; ihevce_hadamard_32x32_8bit(pu1_origin, src_strd, pu1_pred_buf, pred_strd, v, 32); for(k = 0; k < 32 * 32; ++k) u4_sad += abs(v[k]); u4_sad = ((u4_sad + 2) >> 2); return u4_sad; } //#if COMPUTE_16x16_R == C /** ******************************************************************************* * * @brief * Computes 8x8 transform using children 4x4 hadamard results * * @par Description: * * @param[in] pi2_4x4_had * WORD16 pointer to 4x4 hadamard buffer(y0, y1, y2, y3 hadmard in Zscan order) * * @param[in] had4_strd * stride of 4x4 hadmard buffer pi2_y0, pi2_y1, pi2_y2, pi2_y3 * * @param[out] pi2_dst * destination buffer where 8x8 hadamard result is stored * * @param[in] dst_stride * stride of destination block * * @param[in] i4_frm_qstep * frm_qstep value based on the which the threshold value is calculated * * @returns * 8x8 Hadamard SATD * @remarks * ******************************************************************************* */ static UWORD32 ihevce_compute_8x8HAD_using_4x4( WORD16 *pi2_4x4_had, WORD32 had4_strd, WORD16 *pi2_dst, WORD32 dst_strd, WORD32 i4_frm_qstep, WORD32 *pi4_cbf) { /* Qstep value is right shifted by 8 */ WORD32 threshold = (i4_frm_qstep >> 8); /* Initialize pointers to 4 subblocks of 4x4 HAD buffer */ WORD16 *pi2_y0 = pi2_4x4_had; WORD16 *pi2_y1 = pi2_4x4_had + 4; WORD16 *pi2_y2 = pi2_4x4_had + had4_strd * 4; WORD16 *pi2_y3 = pi2_4x4_had + had4_strd * 4 + 4; /* Initialize pointers to store 8x8 HAD output */ WORD16 *pi2_dst0 = pi2_dst; WORD16 *pi2_dst1 = pi2_dst + 4; WORD16 *pi2_dst2 = pi2_dst + dst_strd * 4; WORD16 *pi2_dst3 = pi2_dst + dst_strd * 4 + 4; UWORD32 u4_satd = 0; WORD32 i; /* Child HAD results combined as follows to get Parent result */ /* _ _ */ /* | (y0 + y1) + (y2 + y3) (y0 - y1) + (y2 - y3) | */ /* | (y0 + y1) - (y2 + y3) (y0 - y1) - (y2 - y3) | */ /* \- -/ */ for(i = 0; i < 16; i++) { WORD32 src_idx = (i >> 2) * had4_strd + (i % 4); WORD32 dst_idx = (i >> 2) * dst_strd + (i % 4); WORD16 a0 = pi2_y0[src_idx]; WORD16 a1 = pi2_y1[src_idx]; WORD16 a2 = pi2_y2[src_idx]; WORD16 a3 = pi2_y3[src_idx]; WORD16 b0 = (a0 + a1); WORD16 b1 = (a0 - a1); WORD16 b2 = (a2 + a3); WORD16 b3 = (a2 - a3); pi2_dst0[dst_idx] = b0 + b2; pi2_dst1[dst_idx] = b1 + b3; pi2_dst2[dst_idx] = b0 - b2; pi2_dst3[dst_idx] = b1 - b3; if(ABS(pi2_dst0[dst_idx]) > threshold) *pi4_cbf = 1; if(ABS(pi2_dst1[dst_idx]) > threshold) *pi4_cbf = 1; if(ABS(pi2_dst2[dst_idx]) > threshold) *pi4_cbf = 1; if(ABS(pi2_dst3[dst_idx]) > threshold) *pi4_cbf = 1; u4_satd += ABS(pi2_dst0[dst_idx]); u4_satd += ABS(pi2_dst1[dst_idx]); u4_satd += ABS(pi2_dst2[dst_idx]); u4_satd += ABS(pi2_dst3[dst_idx]); } /* return the 8x8 satd */ return (u4_satd); } /** ******************************************************************************* * * @brief * Computes Residue and Hadamard Transform for four 4x4 blocks (Z scan) of * a 8x8 block (Residue is computed for 8-bit src and prediction buffers) * Modified to incorporate the dead-zone implementation - Lokesh * * @par Description: * * @param[in] pu1_origin * UWORD8 pointer to the current block * * @param[in] src_strd * WORD32 Source stride * * @param[in] pu1_pred * UWORD8 pointer to the prediction block * * @param[in] pred_strd * WORD32 Pred stride * * @param[out] pi2_dst * WORD16 pointer to the transform block * * @param[in] dst_strd * WORD32 Destination stride * * @param[out] pi4_hsad * array for storing hadmard sad of each 4x4 block * * @param[in] hsad_stride * stride of hadmard sad destination buffer (for Zscan order of storing sads) * * @param[in] i4_frm_qstep * frm_qstep value based on the which the threshold value is calculated * * @returns * * @remarks * ******************************************************************************* */ static WORD32 ihevce_had4_4x4( UWORD8 *pu1_src, WORD32 src_strd, UWORD8 *pu1_pred, WORD32 pred_strd, WORD16 *pi2_dst4x4, WORD32 dst_strd, WORD32 *pi4_hsad, WORD32 hsad_stride, WORD32 i4_frm_qstep) { WORD32 i, k; WORD32 i4_child_total_sad = 0; (void)i4_frm_qstep; /* -------- Compute four 4x4 HAD Transforms ---------*/ for(i = 0; i < 4; i++) { UWORD8 *pu1_pi0, *pu1_pi1; WORD16 *pi2_dst; WORD32 blkx, blky; UWORD32 u4_hsad = 0; // TODO: choose deadzone as f(qstep) WORD32 threshold = 0; /*****************************************************/ /* Assuming the looping structure of the four */ /* blocks is in Z scan order of 4x4s in a 8x8 */ /* block instead of raster scan */ /*****************************************************/ blkx = (i & 0x1); blky = (i >> 1); pu1_pi0 = pu1_src + (blkx * 4) + (blky * 4 * src_strd); pu1_pi1 = pu1_pred + (blkx * 4) + (blky * 4 * pred_strd); pi2_dst = pi2_dst4x4 + (blkx * 4) + (blky * 4 * dst_strd); ihevce_hadamard_4x4_8bit(pu1_pi0, src_strd, pu1_pi1, pred_strd, pi2_dst, dst_strd); for(k = 0; k < 4; k++) { if(ABS(pi2_dst[0 * dst_strd + k]) < threshold) pi2_dst[0 * dst_strd + k] = 0; if(ABS(pi2_dst[1 * dst_strd + k]) < threshold) pi2_dst[1 * dst_strd + k] = 0; if(ABS(pi2_dst[2 * dst_strd + k]) < threshold) pi2_dst[2 * dst_strd + k] = 0; if(ABS(pi2_dst[3 * dst_strd + k]) < threshold) pi2_dst[3 * dst_strd + k] = 0; /* Accumulate the SATD */ u4_hsad += ABS(pi2_dst[0 * dst_strd + k]); u4_hsad += ABS(pi2_dst[1 * dst_strd + k]); u4_hsad += ABS(pi2_dst[2 * dst_strd + k]); u4_hsad += ABS(pi2_dst[3 * dst_strd + k]); } /*===== Normalize the HSAD =====*/ pi4_hsad[blkx + (blky * hsad_stride)] = ((u4_hsad + 2) >> 2); i4_child_total_sad += ((u4_hsad + 2) >> 2); } return i4_child_total_sad; } /** ******************************************************************************* * * @brief * HSAD is returned for the 4, 4x4 in 8x8 * * @par Description: * * @param[in] pu1_origin * UWORD8 pointer to the current block * * @param[in] src_strd * WORD32 Source stride * * @param[in] pu1_pred * UWORD8 pointer to the prediction block * * @param[in] pred_strd * WORD32 Pred stride * * @param[out] pi2_dst * WORD16 pointer to the transform output block * * @param[out] dst_strd * WORD32 Destination stride * * @param[out] ppi4_hsad * pointer to base pointers for storing hadmard sads of various * block sizes (4x4 to 32x32) * * @param[in] pos_x_y_4x4 * Denotes packed x,y postion of current 4x4 block w.r.t to start of ctb/CU/MB * Lower 16bits denote xpos and upper 16ypos of the 4x4block * * @param[in] num_4x4_in_row * Denotes the number of current 4x4 blocks in a ctb/CU/MB * * @returns * * @remarks * ******************************************************************************* */ void ihevce_had_8x8_using_4_4x4( UWORD8 *pu1_src, WORD32 src_strd, UWORD8 *pu1_pred, WORD32 pred_strd, WORD16 *pi2_dst, WORD32 dst_strd, WORD32 **ppi4_hsad, WORD32 pos_x_y_4x4, WORD32 num_4x4_in_row) { WORD16 ai2_4x4_had[64]; WORD32 pos_x = pos_x_y_4x4 & 0xFFFF; WORD32 pos_y = (pos_x_y_4x4 >> 16) & 0xFFFF; WORD32 *pi4_4x4_hsad; WORD32 *pi4_8x8_hsad; (void)pi2_dst; (void)dst_strd; ASSERT(pos_x >= 0); ASSERT(pos_y >= 0); /* Initialize pointers to store 4x4 and 8x8 HAD SATDs */ pi4_4x4_hsad = ppi4_hsad[HAD_4x4] + pos_x + pos_y * num_4x4_in_row; pi4_8x8_hsad = ppi4_hsad[HAD_8x8] + (pos_x >> 1) + (pos_y >> 1) * (num_4x4_in_row >> 1); /* -------- Compute four 4x4 HAD Transforms of 8x8 in one call--------- */ pi4_8x8_hsad[0] = ihevce_had4_4x4( pu1_src, src_strd, pu1_pred, pred_strd, ai2_4x4_had, 8, pi4_4x4_hsad, num_4x4_in_row, 0); } /** ******************************************************************************* * * @brief * Reursive Hadamard Transform for 8x8 block. HSAD is returned for the 8x8 * block and its four subblocks(4x4). * * @par Description: * * @param[in] pu1_origin * UWORD8 pointer to the current block * * @param[in] src_strd * WORD32 Source stride * * @param[in] pu1_pred * UWORD8 pointer to the prediction block * * @param[in] pred_strd * WORD32 Pred stride * * @param[out] pi2_dst * WORD16 pointer to the transform output block * * @param[out] dst_strd * WORD32 Destination stride * * @param[out] ppi4_hsad * pointer to base pointers for storing hadmard sads of various * block sizes (4x4 to 32x32) * * @param[in] pos_x_y_4x4 * Denotes packed x,y postion of current 4x4 block w.r.t to start of ctb/CU/MB * Lower 16bits denote xpos and upper 16ypos of the 4x4block * * @param[in] num_4x4_in_row * Denotes the number of current 4x4 blocks in a ctb/CU/MB * * @param[in] i4_frm_qstep * frm_qstep value based on the which the threshold value is calculated * * @returns * * @remarks * ******************************************************************************* */ WORD32 ihevce_had_8x8_using_4_4x4_r( UWORD8 *pu1_src, WORD32 src_strd, UWORD8 *pu1_pred, WORD32 pred_strd, WORD16 *pi2_dst, WORD32 dst_strd, WORD32 **ppi4_hsad, WORD32 **ppi4_tu_split, WORD32 **ppi4_tu_early_cbf, WORD32 pos_x_y_4x4, WORD32 num_4x4_in_row, WORD32 lambda, WORD32 lambda_q_shift, WORD32 i4_frm_qstep, WORD32 i4_cur_depth, WORD32 i4_max_depth, WORD32 i4_max_tr_size, WORD32 *pi4_tu_split_cost, void *pv_func_sel) { WORD16 ai2_4x4_had[64]; WORD32 pos_x = pos_x_y_4x4 & 0xFFFF; WORD32 pos_y = (pos_x_y_4x4 >> 16) & 0xFFFF; WORD32 *pi4_4x4_hsad; WORD32 *pi4_8x8_hsad; WORD32 *pi4_8x8_tu_split; WORD32 *pi4_8x8_tu_early_cbf; UWORD32 u4_satd; WORD32 cost_child = 0, cost_parent = 0; WORD32 early_cbf = 0; const UWORD8 u1_cur_tr_size = 8; /* Stores the best cost for the Current 8x8: Lokesh */ WORD32 best_cost = 0; (void)pv_func_sel; ASSERT(pos_x >= 0); ASSERT(pos_y >= 0); /* Initialize pointers to store 4x4 and 8x8 HAD SATDs */ pi4_4x4_hsad = ppi4_hsad[HAD_4x4] + pos_x + pos_y * num_4x4_in_row; pi4_8x8_hsad = ppi4_hsad[HAD_8x8] + (pos_x >> 1) + (pos_y >> 1) * (num_4x4_in_row >> 1); pi4_8x8_tu_split = ppi4_tu_split[HAD_8x8] + (pos_x >> 1) + (pos_y >> 1) * (num_4x4_in_row >> 1); pi4_8x8_tu_early_cbf = ppi4_tu_early_cbf[HAD_8x8] + (pos_x >> 1) + (pos_y >> 1) * (num_4x4_in_row >> 1); /* -------- Compute four 4x4 HAD Transforms of 8x8 in one call--------- */ cost_child = ihevce_had4_4x4( pu1_src, src_strd, pu1_pred, pred_strd, ai2_4x4_had, 8, pi4_4x4_hsad, num_4x4_in_row, 0); /* -------- Compute 8x8 HAD Transform using 4x4 results ------------- */ u4_satd = ihevce_compute_8x8HAD_using_4x4( ai2_4x4_had, 8, pi2_dst, dst_strd, i4_frm_qstep, &early_cbf); /* store the normalized 8x8 satd */ cost_parent = ((u4_satd + 4) >> 3); /* 4 CBF Flags, extra 1 becoz of the 0.5 bits per bin is assumed */ cost_child += ((4) * lambda) >> (lambda_q_shift + 1); if(i4_cur_depth < i4_max_depth) { if((cost_child < cost_parent) || (i4_max_tr_size < u1_cur_tr_size)) { //cost_child -= ((4) * lambda) >> (lambda_q_shift + 1); *pi4_tu_split_cost += (4 * lambda) >> (lambda_q_shift + 1); best_cost = cost_child; best_cost <<= 1; best_cost++; pi4_8x8_tu_split[0] = 1; pi4_8x8_hsad[0] = cost_child; } else { //cost_parent -= ((1) * lambda) >> (lambda_q_shift + 1); best_cost = cost_parent; best_cost <<= 1; pi4_8x8_tu_split[0] = 0; pi4_8x8_hsad[0] = cost_parent; } } else { //cost_parent -= ((1) * lambda) >> (lambda_q_shift + 1); best_cost = cost_parent; best_cost <<= 1; pi4_8x8_tu_split[0] = 0; pi4_8x8_hsad[0] = cost_parent; } pi4_8x8_tu_early_cbf[0] = early_cbf; /* best cost has tu_split_flag at LSB(Least significant bit) */ return ((best_cost << 1) + early_cbf); } /** ******************************************************************************* * * @brief * Computes 16x16 transform using children 8x8 hadamard results * Modified to incorporate the dead-zone implementation - Lokesh * * @par Description: * * @param[in] pi2_8x8_had * WORD16 pointer to 8x8 hadamard buffer(y0, y1, y2, y3 hadmard in Zscan order) * * @param[in] had8_strd * stride of 8x8 hadmard buffer pi2_y0, pi2_y1, pi2_y2, pi2_y3 * * @param[out] pi2_dst * destination buffer where 8x8 hadamard result is stored * * @param[in] dst_stride * stride of destination block * * @param[in] i4_frm_qstep * frm_qstep value based on the which the threshold value is calculated * * @returns * 16x16 Hadamard SATD * @remarks * ******************************************************************************* */ static UWORD32 ihevce_compute_16x16HAD_using_8x8( WORD16 *pi2_8x8_had, WORD32 had8_strd, WORD16 *pi2_dst, WORD32 dst_strd, WORD32 i4_frm_qstep, WORD32 *pi4_cbf) { /* Qstep value is right shifted by 8 */ WORD32 threshold = (i4_frm_qstep >> 8); /* Initialize pointers to 4 subblocks of 8x8 HAD buffer */ WORD16 *pi2_y0 = pi2_8x8_had; WORD16 *pi2_y1 = pi2_8x8_had + 8; WORD16 *pi2_y2 = pi2_8x8_had + had8_strd * 8; WORD16 *pi2_y3 = pi2_8x8_had + had8_strd * 8 + 8; /* Initialize pointers to store 8x8 HAD output */ WORD16 *pi2_dst0 = pi2_dst; WORD16 *pi2_dst1 = pi2_dst + 8; WORD16 *pi2_dst2 = pi2_dst + dst_strd * 8; WORD16 *pi2_dst3 = pi2_dst + dst_strd * 8 + 8; UWORD32 u4_satd = 0; WORD32 i; /* Child HAD results combined as follows to get Parent result */ /* _ _ */ /* | (y0 + y1) + (y2 + y3) (y0 - y1) + (y2 - y3) | */ /* | (y0 + y1) - (y2 + y3) (y0 - y1) - (y2 - y3) | */ /* \- -/ */ for(i = 0; i < 64; i++) { WORD32 src_idx = (i >> 3) * had8_strd + (i % 8); WORD32 dst_idx = (i >> 3) * dst_strd + (i % 8); WORD16 a0 = pi2_y0[src_idx]; WORD16 a1 = pi2_y1[src_idx]; WORD16 a2 = pi2_y2[src_idx]; WORD16 a3 = pi2_y3[src_idx]; WORD16 b0 = (a0 + a1) >> 1; WORD16 b1 = (a0 - a1) >> 1; WORD16 b2 = (a2 + a3) >> 1; WORD16 b3 = (a2 - a3) >> 1; pi2_dst0[dst_idx] = b0 + b2; pi2_dst1[dst_idx] = b1 + b3; pi2_dst2[dst_idx] = b0 - b2; pi2_dst3[dst_idx] = b1 - b3; /* Make the value of dst to zerp, if it falls below the dead-zone */ if(ABS(pi2_dst0[dst_idx]) > threshold) *pi4_cbf = 1; if(ABS(pi2_dst1[dst_idx]) > threshold) *pi4_cbf = 1; if(ABS(pi2_dst2[dst_idx]) > threshold) *pi4_cbf = 1; if(ABS(pi2_dst3[dst_idx]) > threshold) *pi4_cbf = 1; u4_satd += ABS(pi2_dst0[dst_idx]); u4_satd += ABS(pi2_dst1[dst_idx]); u4_satd += ABS(pi2_dst2[dst_idx]); u4_satd += ABS(pi2_dst3[dst_idx]); } /* return 16x16 satd */ return (u4_satd); } /** ******************************************************************************* * * @brief * Hadamard Transform for 16x16 block with 8x8 and 4x4 SATD updates. * Uses recursive 8x8 had output to compute satd for 16x16 and its children * * @par Description: * * @param[in] pu1_origin * UWORD8 pointer to the current block * * @param[in] src_strd * WORD32 Source stride * * @param[in] pu1_pred * UWORD8 pointer to the prediction block * * @param[in] pred_strd * WORD32 Pred stride * * @param[out] pi2_dst * WORD16 pointer to the transform output block * * @param[out] dst_strd * WORD32 Destination stride * * @param[out] ppi4_hsad * pointer to base pointers for storing hadmard sads of various * block sizes (4x4 to 32x32) * * @param[in] pos_x_y_4x4 * Denotes packed x,y postion of current 4x4 block w.r.t to start of ctb/CU/MB * Lower 16bits denote xpos and upper 16ypos of the 4x4block * * @param[in] num_4x4_in_row * Denotes the number of current 4x4 blocks in a ctb/CU/MB * * @param[in] lambda * lambda values is the cost factor calculated based on QP * * @param[in] lambda_q_shift * lambda_q_shift used to reverse the lambda value back from q8 format * * @param[in] depth * depth gives the current TU depth with respect to the CU * * @param[in] i4_frm_qstep * frm_qstep value based on the which the threshold value is calculated * * @returns * * @remarks * ******************************************************************************* */ WORD32 ihevce_had_16x16_r( UWORD8 *pu1_src, WORD32 src_strd, UWORD8 *pu1_pred, WORD32 pred_strd, WORD16 *pi2_dst, WORD32 dst_strd, WORD32 **ppi4_hsad, WORD32 **ppi4_tu_split, WORD32 **ppi4_tu_early_cbf, WORD32 pos_x_y_4x4, WORD32 num_4x4_in_row, WORD32 lambda, WORD32 lambda_q_shift, WORD32 i4_frm_qstep, WORD32 i4_cur_depth, WORD32 i4_max_depth, WORD32 i4_max_tr_size, WORD32 *pi4_tu_split_cost, void *pv_func_sel) { WORD16 ai2_8x8_had[256]; WORD32 *pi4_16x16_hsad; WORD32 *pi4_16x16_tu_split; WORD32 *pi4_16x16_tu_early_cbf; UWORD32 u4_satd = 0; WORD32 tu_split_flag = 0; WORD32 i4_early_cbf_flag = 0, early_cbf = 0; const UWORD8 u1_cur_tr_size = 16; /* cost_parent : Stores the cost of the parent HAD transform (16x16) */ /* cost_child : Stores the cost of the child HAD transform (16x16) */ WORD32 cost_parent = 0, cost_child = 0; /*best_cost returns the best cost at the end of the function */ /*tu_split denoes whether the TU (16x16)is split or not */ WORD32 best_cost = 0, best_cost_tu_split; WORD32 i; WORD16 *pi2_y0; UWORD8 *pu1_src0; UWORD8 *pu1_pred0; WORD32 pos_x_y_4x4_0; WORD32 pos_x = pos_x_y_4x4 & 0xFFFF; WORD32 pos_y = (pos_x_y_4x4 >> 16) & 0xFFFF; ASSERT(pos_x >= 0); ASSERT(pos_y >= 0); /* Initialize pointers to store 16x16 SATDs */ pi4_16x16_hsad = ppi4_hsad[HAD_16x16] + (pos_x >> 2) + (pos_y >> 2) * (num_4x4_in_row >> 2); pi4_16x16_tu_split = ppi4_tu_split[HAD_16x16] + (pos_x >> 2) + (pos_y >> 2) * (num_4x4_in_row >> 2); pi4_16x16_tu_early_cbf = ppi4_tu_early_cbf[HAD_16x16] + (pos_x >> 2) + (pos_y >> 2) * (num_4x4_in_row >> 2); /* -------- Compute four 8x8 HAD Transforms of 16x16 call--------- */ for(i = 0; i < 4; i++) { pu1_src0 = pu1_src + (i & 0x01) * 8 + (i >> 1) * src_strd * 8; pu1_pred0 = pu1_pred + (i & 0x01) * 8 + (i >> 1) * pred_strd * 8; pi2_y0 = ai2_8x8_had + (i & 0x01) * 8 + (i >> 1) * 16 * 8; pos_x_y_4x4_0 = pos_x_y_4x4 + (i & 0x01) * 2 + (i >> 1) * (2 << 16); best_cost_tu_split = ihevce_had_8x8_using_4_4x4_r( pu1_src0, src_strd, pu1_pred0, pred_strd, pi2_y0, 16, ppi4_hsad, ppi4_tu_split, ppi4_tu_early_cbf, pos_x_y_4x4_0, num_4x4_in_row, lambda, lambda_q_shift, i4_frm_qstep, i4_cur_depth + 1, i4_max_depth, i4_max_tr_size, pi4_tu_split_cost, pv_func_sel); /* Cost is shifted by two bits for Tu_split_flag and early cbf flag */ best_cost = (best_cost_tu_split >> 2); /* Last but one bit stores the information regarding the TU_Split */ tu_split_flag += (best_cost_tu_split & 0x3) >> 1; /* Last bit stores the information regarding the early_cbf */ i4_early_cbf_flag += (best_cost_tu_split & 0x1); cost_child += best_cost; tu_split_flag <<= 1; i4_early_cbf_flag <<= 1; } /* -------- Compute 16x16 HAD Transform using 8x8 results ------------- */ pi2_y0 = ai2_8x8_had; /* Threshold currently passed as "0" */ u4_satd = ihevce_compute_16x16HAD_using_8x8(pi2_y0, 16, pi2_dst, dst_strd, i4_frm_qstep, &early_cbf); /* store the normalized satd */ cost_parent = ((u4_satd + 4) >> 3); /* 4 TU_Split flags , 4 CBF Flags, extra 1 becoz of the 0.5 bits per bin is assumed */ cost_child += ((4 + 4) * lambda) >> (lambda_q_shift + 1); i4_early_cbf_flag += early_cbf; /* Right now the depth is hard-coded to 4: The depth can be modified from the config file which decides the extent to which TU_REC needs to be done */ if(i4_cur_depth < i4_max_depth) { if((cost_child < cost_parent) || (i4_max_tr_size < u1_cur_tr_size)) { //cost_child -= ((4 + 4) * lambda) >> (lambda_q_shift + 1); *pi4_tu_split_cost += ((4 + 4) * lambda) >> (lambda_q_shift + 1); tu_split_flag += 1; best_cost = cost_child; } else { //cost_parent -= ((1 + 1) * lambda) >> (lambda_q_shift + 1); tu_split_flag += 0; best_cost = cost_parent; } } else { //cost_parent -= ((1 + 1) * lambda) >> (lambda_q_shift + 1); tu_split_flag += 0; best_cost = cost_parent; } pi4_16x16_hsad[0] = best_cost; pi4_16x16_tu_split[0] = tu_split_flag; pi4_16x16_tu_early_cbf[0] = i4_early_cbf_flag; /*returning two values(best cost & tu_split_flag) as a single value*/ return ((best_cost << 10) + (tu_split_flag << 5) + i4_early_cbf_flag); } //#endif /** ******************************************************************************* * * @brief * Computes 32x32 transform using children 16x16 hadamard results * * @par Description: * * @param[in] pi2_16x16_had * WORD16 pointer to 16x16 hadamard buffer(y0, y1, y2, y3 hadmard in Zscan order) * * @param[in] had16_strd * stride of 16x16 hadmard buffer pi2_y0, pi2_y1, pi2_y2, pi2_y3 * * @param[out] pi2_dst * destination buffer where 16x16 hadamard result is stored * * @param[in] dst_stride * stride of destination block * * @param[in] i4_frm_qstep * frm_qstep value based on the which the threshold value is calculated * * @returns * 32x32 Hadamard SATD * @remarks * ******************************************************************************* */ //#if COMPUTE_32x32_USING_16X16 == C UWORD32 ihevce_compute_32x32HAD_using_16x16( WORD16 *pi2_16x16_had, WORD32 had16_strd, WORD16 *pi2_dst, WORD32 dst_strd, WORD32 i4_frm_qstep, WORD32 *pi4_cbf) { /* Qstep value is right shifted by 8 */ WORD32 threshold = (i4_frm_qstep >> 8); /* Initialize pointers to 4 subblocks of 8x8 HAD buffer */ WORD16 *pi2_y0 = pi2_16x16_had; WORD16 *pi2_y1 = pi2_16x16_had + 16; WORD16 *pi2_y2 = pi2_16x16_had + had16_strd * 16; WORD16 *pi2_y3 = pi2_16x16_had + had16_strd * 16 + 16; /* Initialize pointers to store 8x8 HAD output */ WORD16 *pi2_dst0 = pi2_dst; WORD16 *pi2_dst1 = pi2_dst + 16; WORD16 *pi2_dst2 = pi2_dst + dst_strd * 16; WORD16 *pi2_dst3 = pi2_dst + dst_strd * 16 + 16; UWORD32 u4_satd = 0; WORD32 i; /* Child HAD results combined as follows to get Parent result */ /* _ _ */ /* | (y0 + y1) + (y2 + y3) (y0 - y1) + (y2 - y3) | */ /* | (y0 + y1) - (y2 + y3) (y0 - y1) - (y2 - y3) | */ /* \- -/ */ for(i = 0; i < 256; i++) { WORD32 src_idx = (i >> 4) * had16_strd + (i % 16); WORD32 dst_idx = (i >> 4) * dst_strd + (i % 16); WORD16 a0 = pi2_y0[src_idx] >> 2; WORD16 a1 = pi2_y1[src_idx] >> 2; WORD16 a2 = pi2_y2[src_idx] >> 2; WORD16 a3 = pi2_y3[src_idx] >> 2; WORD16 b0 = (a0 + a1); WORD16 b1 = (a0 - a1); WORD16 b2 = (a2 + a3); WORD16 b3 = (a2 - a3); pi2_dst0[dst_idx] = b0 + b2; pi2_dst1[dst_idx] = b1 + b3; pi2_dst2[dst_idx] = b0 - b2; pi2_dst3[dst_idx] = b1 - b3; /* Make the value of dst to zerp, if it falls below the dead-zone */ if(ABS(pi2_dst0[dst_idx]) > threshold) *pi4_cbf = 1; if(ABS(pi2_dst1[dst_idx]) > threshold) *pi4_cbf = 1; if(ABS(pi2_dst2[dst_idx]) > threshold) *pi4_cbf = 1; if(ABS(pi2_dst3[dst_idx]) > threshold) *pi4_cbf = 1; u4_satd += ABS(pi2_dst0[dst_idx]); u4_satd += ABS(pi2_dst1[dst_idx]); u4_satd += ABS(pi2_dst2[dst_idx]); u4_satd += ABS(pi2_dst3[dst_idx]); } /* return 32x32 satd */ return (u4_satd); } //#endif /** ******************************************************************************* * * @brief * Hadamard Transform for 32x32 block with 16x6, 8x8 and 4x4 SATD updates. * Uses recursive 16x16 had output to compute satd for 32x32 and its children * * @par Description: * * @param[in] pu1_origin * UWORD8 pointer to the current block * * @param[in] src_strd * WORD32 Source stride * * @param[in] pu1_pred * UWORD8 pointer to the prediction block * * @param[in] pred_strd * WORD32 Pred stride * * @param[out] pi2_dst * WORD16 pointer to the transform output block * * @param[out] dst_strd * WORD32 Destination stride * * @param[out] ppi4_hsad * pointer to base pointers for storing hadmard sads of various * block sizes (4x4 to 32x32) * * @param[in] pos_x_y_4x4 * Denotes packed x,y postion of current 4x4 block w.r.t to start of ctb/CU/MB * Lower 16bits denote xpos and upper 16ypos of the 4x4block * * @param[in] num_4x4_in_row * Denotes the number of current 4x4 blocks in a ctb/CU/MB * * @param[in] lambda * lambda values is the cost factor calculated based on QP * * @param[in] lambda_q_shift * lambda_q_shift used to reverse the lambda value back from q8 format * * @param[in] depth * depth gives the current TU depth with respect to the CU * * @param[in] i4_frm_qstep * frm_qstep value based on the which the threshold value is calculated * * * @returns * * @remarks * ******************************************************************************* */ void ihevce_had_32x32_r( UWORD8 *pu1_src, WORD32 src_strd, UWORD8 *pu1_pred, WORD32 pred_strd, WORD16 *pi2_dst, WORD32 dst_strd, WORD32 **ppi4_hsad, WORD32 **ppi4_tu_split, WORD32 **ppi4_tu_early_cbf, WORD32 pos_x_y_4x4, WORD32 num_4x4_in_row, WORD32 lambda, WORD32 lambda_q_shift, WORD32 i4_frm_qstep, WORD32 i4_cur_depth, WORD32 i4_max_depth, WORD32 i4_max_tr_size, WORD32 *pi4_tu_split_cost, me_func_selector_t *ps_func_selector) { WORD16 ai2_16x16_had[1024]; WORD32 *pi4_32x32_hsad; WORD32 *pi4_32x32_tu_split; WORD32 *pi4_32x32_tu_early_cbf; WORD32 pos_x = pos_x_y_4x4 & 0xFFFF; WORD32 pos_y = (pos_x_y_4x4 >> 16) & 0xFFFF; WORD32 tu_split_flag = 0; const UWORD8 u1_cur_tr_size = 32; WORD32 i4_early_cbf_flag = 0, early_cbf = 0; /* cost_parent : Stores the cost of the parent HAD transform (16x16) */ /* cost_child : Stores the cost of the child HAD transform (16x16) */ WORD32 cost_child = 0, cost_parent = 0; /*retuned as the best cost for the entire TU (32x32) */ WORD32 best_cost = 0; /*captures the best cost and tu_split at child level */ WORD32 best_cost_tu_split; /* Initialize pointers to 4 8x8 blocks in 16x16 */ WORD16 *pi2_y0 = ai2_16x16_had; WORD16 *pi2_y1 = ai2_16x16_had + 16; WORD16 *pi2_y2 = ai2_16x16_had + 32 * 16; WORD16 *pi2_y3 = ai2_16x16_had + 32 * 16 + 16; UWORD8 *pu1_src0 = pu1_src; UWORD8 *pu1_src1 = pu1_src + 16; UWORD8 *pu1_src2 = pu1_src + src_strd * 16; UWORD8 *pu1_src3 = pu1_src + src_strd * 16 + 16; UWORD8 *pu1_pred0 = pu1_pred; UWORD8 *pu1_pred1 = pu1_pred + 16; UWORD8 *pu1_pred2 = pu1_pred + pred_strd * 16; UWORD8 *pu1_pred3 = pu1_pred + pred_strd * 16 + 16; ASSERT(pos_x >= 0); ASSERT(pos_y >= 0); /* Initialize pointers to store 32x32 SATDs */ pi4_32x32_hsad = ppi4_hsad[HAD_32x32] + (pos_x >> 3) + (pos_y >> 3) * (num_4x4_in_row >> 3); pi4_32x32_tu_split = ppi4_tu_split[HAD_32x32] + (pos_x >> 3) + (pos_y >> 3) * (num_4x4_in_row >> 3); pi4_32x32_tu_early_cbf = ppi4_tu_early_cbf[HAD_32x32] + (pos_x >> 3) + (pos_y >> 3) * (num_4x4_in_row >> 3); /* -------- Compute four 8x8 HAD Transforms of 16x16 call--------- */ best_cost_tu_split = ps_func_selector->pf_had_16x16_r( pu1_src0, src_strd, pu1_pred0, pred_strd, pi2_y0, 32, ppi4_hsad, ppi4_tu_split, ppi4_tu_early_cbf, pos_x_y_4x4, num_4x4_in_row, lambda, lambda_q_shift, i4_frm_qstep, i4_cur_depth + 1, i4_max_depth, i4_max_tr_size, pi4_tu_split_cost, NULL); /* cost is shifted by 10bits */ best_cost = best_cost_tu_split >> 10; /* Tu split is present in the 6-10 bits */ tu_split_flag += (best_cost_tu_split & 0x3E0) >> 5; /*Early CBF info is present in the last 5 bits */ i4_early_cbf_flag += best_cost_tu_split & 0x1F; tu_split_flag <<= 5; i4_early_cbf_flag <<= 5; cost_child += best_cost; best_cost_tu_split = ps_func_selector->pf_had_16x16_r( pu1_src1, src_strd, pu1_pred1, pred_strd, pi2_y1, 32, ppi4_hsad, ppi4_tu_split, ppi4_tu_early_cbf, pos_x_y_4x4 + 4, num_4x4_in_row, lambda, lambda_q_shift, i4_frm_qstep, i4_cur_depth + 1, i4_max_depth, i4_max_tr_size, pi4_tu_split_cost, NULL); /* cost is shifted by 10bits */ best_cost = best_cost_tu_split >> 10; /* Tu split is present in the 6-10 bits */ tu_split_flag += (best_cost_tu_split & 0x3E0) >> 5; /*Early CBF info is present in the last 5 bits */ i4_early_cbf_flag += best_cost_tu_split & 0x1F; tu_split_flag <<= 5; i4_early_cbf_flag <<= 5; cost_child += best_cost; best_cost_tu_split = ps_func_selector->pf_had_16x16_r( pu1_src2, src_strd, pu1_pred2, pred_strd, pi2_y2, 32, ppi4_hsad, ppi4_tu_split, ppi4_tu_early_cbf, pos_x_y_4x4 + (4 << 16), num_4x4_in_row, lambda, lambda_q_shift, i4_frm_qstep, i4_cur_depth + 1, i4_max_depth, i4_max_tr_size, pi4_tu_split_cost, NULL); /* cost is shifted by 10bits */ best_cost = best_cost_tu_split >> 10; /* Tu split is present in the 6-10 bits */ tu_split_flag += (best_cost_tu_split & 0x3E0) >> 5; /*Early CBF info is present in the last 5 bits */ i4_early_cbf_flag += best_cost_tu_split & 0x1F; tu_split_flag <<= 5; i4_early_cbf_flag <<= 5; cost_child += best_cost; best_cost_tu_split = ps_func_selector->pf_had_16x16_r( pu1_src3, src_strd, pu1_pred3, pred_strd, pi2_y3, 32, ppi4_hsad, ppi4_tu_split, ppi4_tu_early_cbf, pos_x_y_4x4 + (4 << 16) + 4, num_4x4_in_row, lambda, lambda_q_shift, i4_frm_qstep, i4_cur_depth + 1, i4_max_depth, i4_max_tr_size, pi4_tu_split_cost, NULL); /* cost is shifted by 10bits */ best_cost = best_cost_tu_split >> 10; /* Tu split is present in the 6-10 bits */ tu_split_flag += (best_cost_tu_split & 0x3E0) >> 5; /*Early CBF info is present in the last 5 bits */ i4_early_cbf_flag += best_cost_tu_split & 0x1F; tu_split_flag <<= 1; i4_early_cbf_flag <<= 1; cost_child += best_cost; { UWORD32 u4_satd = 0; u4_satd = ps_func_selector->pf_compute_32x32HAD_using_16x16( pi2_y0, 32, pi2_dst, dst_strd, i4_frm_qstep, &early_cbf); cost_parent = ((u4_satd + 2) >> 2); } /* 4 TU_Split flags , 4 CBF Flags*/ cost_child += ((4 + 4) * lambda) >> (lambda_q_shift + 1); i4_early_cbf_flag += early_cbf; /* 1 TU_SPlit flag, 1 CBF flag */ //cost_parent += ((1 + 1)* lambda) >> (lambda_q_shift + 1); if(i4_cur_depth < i4_max_depth) { if((cost_child < cost_parent) || (u1_cur_tr_size > i4_max_tr_size)) { *pi4_tu_split_cost += ((4 + 4) * lambda) >> (lambda_q_shift + 1); best_cost = cost_child; tu_split_flag++; } else { tu_split_flag = 0; best_cost = cost_parent; } } else { tu_split_flag = 0; best_cost = cost_parent; } pi4_32x32_tu_split[0] = tu_split_flag; pi4_32x32_hsad[0] = best_cost; pi4_32x32_tu_early_cbf[0] = i4_early_cbf_flag; }