/****************************************************************************** * * Copyright (C) 2015 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 ime_distortion_metrics_sse42.c * * @brief * This file contains definitions of routines that compute distortion * between two macro/sub blocks of identical dimensions * * @author * Ittiam * * @par List of Functions: * - ime_compute_sad_16x16_sse42() * - ime_compute_sad_16x16_fast_sse42() * - ime_compute_sad_16x16_ea8_sse42() * - ime_compute_sad_16x8_sse42() * - ime_calculate_sad4_prog_sse42() * - ime_sub_pel_compute_sad_16x16_sse42() * - ime_compute_satqd_16x16_lumainter_sse42() * * @remarks * None * ******************************************************************************* */ /*****************************************************************************/ /* File Includes */ /*****************************************************************************/ /* System include files */ #include <stdio.h> #include <stdlib.h> #include <string.h> /* User include files */ #include "ime_typedefs.h" #include "ime_defs.h" #include "ime_macros.h" #include "ime_statistics.h" #include "ime_platform_macros.h" #include "ime_distortion_metrics.h" #include <immintrin.h> /*****************************************************************************/ /* Function Definitions */ /*****************************************************************************/ /** ****************************************************************************** * * @brief computes distortion (SAD) between 2 16x16 blocks * * @par Description * This functions computes SAD between 2 16x16 blocks. There is a provision * for early exit if the up-to computed SAD exceeds maximum allowed SAD. To * compute the distortion of the entire block set u4_max_sad to USHRT_MAX. * * @param[in] pu1_src * UWORD8 pointer to the source * * @param[out] pu1_dst * UWORD8 pointer to the destination * * @param[in] src_strd * integer source stride * * @param[in] dst_strd * integer destination stride * * @param[in] i4_max_sad * integer maximum allowed distortion * * @param[out] pi4_mb_distortion * integer evaluated sad * * @remarks * ****************************************************************************** */ void ime_compute_sad_16x16_sse42(UWORD8 *pu1_src, UWORD8 *pu1_est, WORD32 src_strd, WORD32 est_strd, WORD32 i4_max_sad, WORD32 *pi4_mb_distortion) { __m128i src_r0, src_r1, src_r2, src_r3; __m128i est_r0, est_r1, est_r2, est_r3; __m128i res_r0, res_r1, res_r2, res_r3; __m128i sad_val; int val1, val2; UNUSED (i4_max_sad); // Row 0-3 sad calculation src_r0 = _mm_loadu_si128((__m128i *) (pu1_src)); src_r1 = _mm_loadu_si128((__m128i *) (pu1_src + src_strd)); src_r2 = _mm_loadu_si128((__m128i *) (pu1_src + 2*src_strd)); src_r3 = _mm_loadu_si128((__m128i *) (pu1_src + 3*src_strd)); est_r0 = _mm_loadu_si128((__m128i *) (pu1_est)); est_r1 = _mm_loadu_si128((__m128i *) (pu1_est + est_strd)); est_r2 = _mm_loadu_si128((__m128i *) (pu1_est + 2*est_strd)); est_r3 = _mm_loadu_si128((__m128i *) (pu1_est + 3*est_strd)); res_r0 = _mm_sad_epu8(src_r0, est_r0); res_r1 = _mm_sad_epu8(src_r1, est_r1); res_r2 = _mm_sad_epu8(src_r2, est_r2); res_r3 = _mm_sad_epu8(src_r3, est_r3); sad_val = _mm_add_epi64(res_r0, res_r1); sad_val = _mm_add_epi64(sad_val, res_r2); sad_val = _mm_add_epi64(sad_val, res_r3); // Row 4-7 sad calculation pu1_src += 4*src_strd; pu1_est += 4*est_strd; src_r0 = _mm_loadu_si128((__m128i *) (pu1_src)); src_r1 = _mm_loadu_si128((__m128i *) (pu1_src + src_strd)); src_r2 = _mm_loadu_si128((__m128i *) (pu1_src + 2*src_strd)); src_r3 = _mm_loadu_si128((__m128i *) (pu1_src + 3*src_strd)); est_r0 = _mm_loadu_si128((__m128i *) (pu1_est)); est_r1 = _mm_loadu_si128((__m128i *) (pu1_est + est_strd)); est_r2 = _mm_loadu_si128((__m128i *) (pu1_est + 2*est_strd)); est_r3 = _mm_loadu_si128((__m128i *) (pu1_est + 3*est_strd)); res_r0 = _mm_sad_epu8(src_r0, est_r0); res_r1 = _mm_sad_epu8(src_r1, est_r1); res_r2 = _mm_sad_epu8(src_r2, est_r2); res_r3 = _mm_sad_epu8(src_r3, est_r3); sad_val = _mm_add_epi64(sad_val, res_r0); sad_val = _mm_add_epi64(sad_val, res_r1); sad_val = _mm_add_epi64(sad_val, res_r2); sad_val = _mm_add_epi64(sad_val, res_r3); // Row 8-11 sad calculation pu1_src += 4*src_strd; pu1_est += 4*est_strd; src_r0 = _mm_loadu_si128((__m128i *) (pu1_src)); src_r1 = _mm_loadu_si128((__m128i *) (pu1_src + src_strd)); src_r2 = _mm_loadu_si128((__m128i *) (pu1_src + 2*src_strd)); src_r3 = _mm_loadu_si128((__m128i *) (pu1_src + 3*src_strd)); est_r0 = _mm_loadu_si128((__m128i *) (pu1_est)); est_r1 = _mm_loadu_si128((__m128i *) (pu1_est + est_strd)); est_r2 = _mm_loadu_si128((__m128i *) (pu1_est + 2*est_strd)); est_r3 = _mm_loadu_si128((__m128i *) (pu1_est + 3*est_strd)); res_r0 = _mm_sad_epu8(src_r0, est_r0); res_r1 = _mm_sad_epu8(src_r1, est_r1); res_r2 = _mm_sad_epu8(src_r2, est_r2); res_r3 = _mm_sad_epu8(src_r3, est_r3); sad_val = _mm_add_epi64(sad_val, res_r0); sad_val = _mm_add_epi64(sad_val, res_r1); sad_val = _mm_add_epi64(sad_val, res_r2); sad_val = _mm_add_epi64(sad_val, res_r3); // Row 12-15 sad calculation pu1_src += 4*src_strd; pu1_est += 4*est_strd; src_r0 = _mm_loadu_si128((__m128i *) (pu1_src)); src_r1 = _mm_loadu_si128((__m128i *) (pu1_src + src_strd)); src_r2 = _mm_loadu_si128((__m128i *) (pu1_src + 2*src_strd)); src_r3 = _mm_loadu_si128((__m128i *) (pu1_src + 3*src_strd)); est_r0 = _mm_loadu_si128((__m128i *) (pu1_est)); est_r1 = _mm_loadu_si128((__m128i *) (pu1_est + est_strd)); est_r2 = _mm_loadu_si128((__m128i *) (pu1_est + 2*est_strd)); est_r3 = _mm_loadu_si128((__m128i *) (pu1_est + 3*est_strd)); res_r0 = _mm_sad_epu8(src_r0, est_r0); res_r1 = _mm_sad_epu8(src_r1, est_r1); res_r2 = _mm_sad_epu8(src_r2, est_r2); res_r3 = _mm_sad_epu8(src_r3, est_r3); sad_val = _mm_add_epi64(sad_val, res_r0); sad_val = _mm_add_epi64(sad_val, res_r1); sad_val = _mm_add_epi64(sad_val, res_r2); sad_val = _mm_add_epi64(sad_val, res_r3); val1 = _mm_extract_epi32(sad_val,0); val2 = _mm_extract_epi32(sad_val, 2); *pi4_mb_distortion = (val1+val2); return; } /** ****************************************************************************** * * @brief computes distortion (SAD) between 2 16x8 blocks * * * @par Description * This functions computes SAD between 2 16x8 blocks. There is a provision * for early exit if the up-to computed SAD exceeds maximum allowed SAD. To * compute the distortion of the entire block set u4_max_sad to USHRT_MAX. * * @param[in] pu1_src * UWORD8 pointer to the source * * @param[out] pu1_dst * UWORD8 pointer to the destination * * @param[in] src_strd * integer source stride * * @param[in] dst_strd * integer destination stride * * @param[in] u4_max_sad * integer maximum allowed distortion * * @param[out] pi4_mb_distortion * integer evaluated sad * * @remarks * ****************************************************************************** */ void ime_compute_sad_16x8_sse42(UWORD8 *pu1_src, UWORD8 *pu1_est, WORD32 src_strd, WORD32 est_strd, WORD32 i4_max_sad, WORD32 *pi4_mb_distortion) { __m128i src_r0, src_r1, src_r2, src_r3; __m128i est_r0, est_r1, est_r2, est_r3; __m128i res_r0, res_r1, res_r2, res_r3; __m128i sad_val; int val1, val2; UNUSED (i4_max_sad); // Row 0-3 sad calculation src_r0 = _mm_loadu_si128((__m128i *) (pu1_src)); src_r1 = _mm_loadu_si128((__m128i *) (pu1_src + src_strd)); src_r2 = _mm_loadu_si128((__m128i *) (pu1_src + 2*src_strd)); src_r3 = _mm_loadu_si128((__m128i *) (pu1_src + 3*src_strd)); est_r0 = _mm_loadu_si128((__m128i *) (pu1_est)); est_r1 = _mm_loadu_si128((__m128i *) (pu1_est + est_strd)); est_r2 = _mm_loadu_si128((__m128i *) (pu1_est + 2*est_strd)); est_r3 = _mm_loadu_si128((__m128i *) (pu1_est + 3*est_strd)); res_r0 = _mm_sad_epu8(src_r0, est_r0); res_r1 = _mm_sad_epu8(src_r1, est_r1); res_r2 = _mm_sad_epu8(src_r2, est_r2); res_r3 = _mm_sad_epu8(src_r3, est_r3); sad_val = _mm_add_epi64(res_r0, res_r1); sad_val = _mm_add_epi64(sad_val, res_r2); sad_val = _mm_add_epi64(sad_val, res_r3); // Row 4-7 sad calculation pu1_src += 4*src_strd; pu1_est += 4*est_strd; src_r0 = _mm_loadu_si128((__m128i *) (pu1_src)); src_r1 = _mm_loadu_si128((__m128i *) (pu1_src + src_strd)); src_r2 = _mm_loadu_si128((__m128i *) (pu1_src + 2*src_strd)); src_r3 = _mm_loadu_si128((__m128i *) (pu1_src + 3*src_strd)); est_r0 = _mm_loadu_si128((__m128i *) (pu1_est)); est_r1 = _mm_loadu_si128((__m128i *) (pu1_est + est_strd)); est_r2 = _mm_loadu_si128((__m128i *) (pu1_est + 2*est_strd)); est_r3 = _mm_loadu_si128((__m128i *) (pu1_est + 3*est_strd)); res_r0 = _mm_sad_epu8(src_r0, est_r0); res_r1 = _mm_sad_epu8(src_r1, est_r1); res_r2 = _mm_sad_epu8(src_r2, est_r2); res_r3 = _mm_sad_epu8(src_r3, est_r3); sad_val = _mm_add_epi64(sad_val, res_r0); sad_val = _mm_add_epi64(sad_val, res_r1); sad_val = _mm_add_epi64(sad_val, res_r2); sad_val = _mm_add_epi64(sad_val, res_r3); val1 = _mm_extract_epi32(sad_val,0); val2 = _mm_extract_epi32(sad_val, 2); *pi4_mb_distortion = (val1+val2); return; } /** ****************************************************************************** * * @brief computes distortion (SAD) between 2 16x16 blocks * * @par Description * This functions computes SAD between 2 16x16 blocks. There is a provision * for early exit if the up-to computed SAD exceeds maximum allowed SAD. To * compute the distortion of the entire block set u4_max_sad to USHRT_MAX. * * @param[in] pu1_src * UWORD8 pointer to the source * * @param[out] pu1_dst * UWORD8 pointer to the destination * * @param[in] src_strd * integer source stride * * @param[in] dst_strd * integer destination stride * * @param[in] i4_max_sad * integer maximum allowed distortion * * @param[out] pi4_mb_distortion * integer evaluated sad * * @remarks * ****************************************************************************** */ void ime_compute_sad_16x16_ea8_sse42(UWORD8 *pu1_src, UWORD8 *pu1_est, WORD32 src_strd, WORD32 est_strd, WORD32 i4_max_sad, WORD32 *pi4_mb_distortion) { __m128i src_r0, src_r1, src_r2, src_r3; __m128i est_r0, est_r1, est_r2, est_r3; __m128i res_r0, res_r1, res_r2, res_r3; __m128i sad_val; WORD32 val1, val2; WORD32 i4_sad; UWORD8 *pu1_src_temp = pu1_src + src_strd; UWORD8 *pu1_est_temp = pu1_est + est_strd; // Row 0,2,4,6 sad calculation src_r0 = _mm_loadu_si128((__m128i *) (pu1_src)); src_r1 = _mm_loadu_si128((__m128i *) (pu1_src + 2*src_strd)); src_r2 = _mm_loadu_si128((__m128i *) (pu1_src + 4*src_strd)); src_r3 = _mm_loadu_si128((__m128i *) (pu1_src + 6*src_strd)); est_r0 = _mm_loadu_si128((__m128i *) (pu1_est)); est_r1 = _mm_loadu_si128((__m128i *) (pu1_est + 2*est_strd)); est_r2 = _mm_loadu_si128((__m128i *) (pu1_est + 4*est_strd)); est_r3 = _mm_loadu_si128((__m128i *) (pu1_est + 6*est_strd)); res_r0 = _mm_sad_epu8(src_r0, est_r0); res_r1 = _mm_sad_epu8(src_r1, est_r1); res_r2 = _mm_sad_epu8(src_r2, est_r2); res_r3 = _mm_sad_epu8(src_r3, est_r3); sad_val = _mm_add_epi64(res_r0, res_r1); sad_val = _mm_add_epi64(sad_val, res_r2); sad_val = _mm_add_epi64(sad_val, res_r3); // Row 8,10,12,14 sad calculation pu1_src += 8*src_strd; pu1_est += 8*est_strd; src_r0 = _mm_loadu_si128((__m128i *) (pu1_src)); src_r1 = _mm_loadu_si128((__m128i *) (pu1_src + 2*src_strd)); src_r2 = _mm_loadu_si128((__m128i *) (pu1_src + 4*src_strd)); src_r3 = _mm_loadu_si128((__m128i *) (pu1_src + 6*src_strd)); est_r0 = _mm_loadu_si128((__m128i *) (pu1_est)); est_r1 = _mm_loadu_si128((__m128i *) (pu1_est + 2*est_strd)); est_r2 = _mm_loadu_si128((__m128i *) (pu1_est + 4*est_strd)); est_r3 = _mm_loadu_si128((__m128i *) (pu1_est + 6*est_strd)); res_r0 = _mm_sad_epu8(src_r0, est_r0); res_r1 = _mm_sad_epu8(src_r1, est_r1); res_r2 = _mm_sad_epu8(src_r2, est_r2); res_r3 = _mm_sad_epu8(src_r3, est_r3); sad_val = _mm_add_epi64(sad_val, res_r0); sad_val = _mm_add_epi64(sad_val, res_r1); sad_val = _mm_add_epi64(sad_val, res_r2); sad_val = _mm_add_epi64(sad_val, res_r3); pu1_src = pu1_src_temp; pu1_est = pu1_est_temp; val1 = _mm_extract_epi32(sad_val, 0); val2 = _mm_extract_epi32(sad_val, 2); i4_sad = val1 + val2; if (i4_max_sad < i4_sad) { *pi4_mb_distortion = i4_sad; return ; } // Row 1,3,5,7 sad calculation src_r0 = _mm_loadu_si128((__m128i *) (pu1_src)); src_r1 = _mm_loadu_si128((__m128i *) (pu1_src + 2*src_strd)); src_r2 = _mm_loadu_si128((__m128i *) (pu1_src + 4*src_strd)); src_r3 = _mm_loadu_si128((__m128i *) (pu1_src + 6*src_strd)); est_r0 = _mm_loadu_si128((__m128i *) (pu1_est)); est_r1 = _mm_loadu_si128((__m128i *) (pu1_est + 2*est_strd)); est_r2 = _mm_loadu_si128((__m128i *) (pu1_est + 4*est_strd)); est_r3 = _mm_loadu_si128((__m128i *) (pu1_est + 6*est_strd)); res_r0 = _mm_sad_epu8(src_r0, est_r0); res_r1 = _mm_sad_epu8(src_r1, est_r1); res_r2 = _mm_sad_epu8(src_r2, est_r2); res_r3 = _mm_sad_epu8(src_r3, est_r3); sad_val = _mm_add_epi64(sad_val, res_r0); sad_val = _mm_add_epi64(sad_val, res_r1); sad_val = _mm_add_epi64(sad_val, res_r2); sad_val = _mm_add_epi64(sad_val, res_r3); // Row 9,11,13,15 sad calculation pu1_src += 8*src_strd; pu1_est += 8*est_strd; src_r0 = _mm_loadu_si128((__m128i *) (pu1_src)); src_r1 = _mm_loadu_si128((__m128i *) (pu1_src + 2*src_strd)); src_r2 = _mm_loadu_si128((__m128i *) (pu1_src + 4*src_strd)); src_r3 = _mm_loadu_si128((__m128i *) (pu1_src + 6*src_strd)); est_r0 = _mm_loadu_si128((__m128i *) (pu1_est)); est_r1 = _mm_loadu_si128((__m128i *) (pu1_est + 2*est_strd)); est_r2 = _mm_loadu_si128((__m128i *) (pu1_est + 4*est_strd)); est_r3 = _mm_loadu_si128((__m128i *) (pu1_est + 6*est_strd)); res_r0 = _mm_sad_epu8(src_r0, est_r0); res_r1 = _mm_sad_epu8(src_r1, est_r1); res_r2 = _mm_sad_epu8(src_r2, est_r2); res_r3 = _mm_sad_epu8(src_r3, est_r3); sad_val = _mm_add_epi64(sad_val, res_r0); sad_val = _mm_add_epi64(sad_val, res_r1); sad_val = _mm_add_epi64(sad_val, res_r2); sad_val = _mm_add_epi64(sad_val, res_r3); val1 = _mm_extract_epi32(sad_val, 0); val2 = _mm_extract_epi32(sad_val, 2); *pi4_mb_distortion = (val1+val2); return; } /** ****************************************************************************** * * @brief computes distortion (SAD) between 2 16x16 blocks (fast mode) * * @par Description * This functions computes SAD between 2 16x16 blocks by processing alternate * rows (fast mode). For fast mode it is assumed sad obtained by processing * alternate rows is approximately twice as that for the whole block. * * @param[in] pu1_src * UWORD8 pointer to the source * * @param[out] pu1_dst * UWORD8 pointer to the destination * * @param[in] src_strd * integer source stride * * @param[in] dst_strd * integer destination stride * * @param[in] i4_max_sad * integer maximum allowed distortion * * @param[out] pi4_mb_distortion * integer evaluated sad * * @remarks * ****************************************************************************** */ void ime_compute_sad_16x16_fast_sse42(UWORD8 *pu1_src, UWORD8 *pu1_est, WORD32 src_strd, WORD32 est_strd, WORD32 i4_max_sad, WORD32 *pi4_mb_distortion) { __m128i src_r0, src_r1, src_r2, src_r3; __m128i est_r0, est_r1, est_r2, est_r3; __m128i res_r0, res_r1, res_r2, res_r3; __m128i sad_val; WORD32 val1, val2; WORD32 i4_sad; UWORD8 *pu1_src_temp = pu1_src + src_strd; UWORD8 *pu1_est_temp = pu1_est + est_strd; UNUSED (i4_max_sad); // Row 0,2,4,6 sad calculation src_r0 = _mm_loadu_si128((__m128i *) (pu1_src)); src_r1 = _mm_loadu_si128((__m128i *) (pu1_src + 2 * src_strd)); src_r2 = _mm_loadu_si128((__m128i *) (pu1_src + 4 * src_strd)); src_r3 = _mm_loadu_si128((__m128i *) (pu1_src + 6 * src_strd)); est_r0 = _mm_loadu_si128((__m128i *) (pu1_est)); est_r1 = _mm_loadu_si128((__m128i *) (pu1_est + 2 * est_strd)); est_r2 = _mm_loadu_si128((__m128i *) (pu1_est + 4 * est_strd)); est_r3 = _mm_loadu_si128((__m128i *) (pu1_est + 6 * est_strd)); res_r0 = _mm_sad_epu8(src_r0, est_r0); res_r1 = _mm_sad_epu8(src_r1, est_r1); res_r2 = _mm_sad_epu8(src_r2, est_r2); res_r3 = _mm_sad_epu8(src_r3, est_r3); sad_val = _mm_add_epi64(res_r0, res_r1); sad_val = _mm_add_epi64(sad_val, res_r2); sad_val = _mm_add_epi64(sad_val, res_r3); // Row 8,10,12,14 sad calculation pu1_src += 8 * src_strd; pu1_est += 8 * est_strd; src_r0 = _mm_loadu_si128((__m128i *) (pu1_src)); src_r1 = _mm_loadu_si128((__m128i *) (pu1_src + 2 * src_strd)); src_r2 = _mm_loadu_si128((__m128i *) (pu1_src + 4 * src_strd)); src_r3 = _mm_loadu_si128((__m128i *) (pu1_src + 6 * src_strd)); est_r0 = _mm_loadu_si128((__m128i *) (pu1_est)); est_r1 = _mm_loadu_si128((__m128i *) (pu1_est + 2 * est_strd)); est_r2 = _mm_loadu_si128((__m128i *) (pu1_est + 4 * est_strd)); est_r3 = _mm_loadu_si128((__m128i *) (pu1_est + 6 * est_strd)); res_r0 = _mm_sad_epu8(src_r0, est_r0); res_r1 = _mm_sad_epu8(src_r1, est_r1); res_r2 = _mm_sad_epu8(src_r2, est_r2); res_r3 = _mm_sad_epu8(src_r3, est_r3); sad_val = _mm_add_epi64(sad_val, res_r0); sad_val = _mm_add_epi64(sad_val, res_r1); sad_val = _mm_add_epi64(sad_val, res_r2); sad_val = _mm_add_epi64(sad_val, res_r3); pu1_src = pu1_src_temp; pu1_est = pu1_est_temp; val1 = _mm_extract_epi32(sad_val, 0); val2 = _mm_extract_epi32(sad_val, 2); i4_sad = val1 + val2; *pi4_mb_distortion = (i4_sad<<1); return; } /** ******************************************************************************* * * @brief compute sad * * @par Description: This function computes the sad at vertices of diamond grid * centered at reference pointer and at unit distance from it. * * @param[in] pu1_ref * UWORD8 pointer to the reference * * @param[out] pu1_src * UWORD8 pointer to the source * * @param[in] ref_strd * integer reference stride * * @param[in] src_strd * integer source stride * * @param[out] pi4_sad * pointer to integer array evaluated sad * * @returns sad at all evaluated vertexes * * @remarks none * ******************************************************************************* */ void ime_calculate_sad4_prog_sse42(UWORD8 *pu1_ref, UWORD8 *pu1_src, WORD32 ref_strd, WORD32 src_strd, WORD32 *pi4_sad) { /* reference ptrs at unit 1 distance in diamond pattern centered at pu1_ref */ UWORD8 *left_ptr = pu1_ref - 1; UWORD8 *right_ptr = pu1_ref + 1; UWORD8 *top_ptr = pu1_ref - ref_strd; UWORD8 *bot_ptr = pu1_ref + ref_strd; WORD32 val1, val2; __m128i src, ref_left, ref_right, ref_top, ref_bot; __m128i res_r0, res_r1, res_r2, res_r3; __m128i sad_r0, sad_r1, sad_r2, sad_r3; // Row 0 sad calculation src = _mm_loadu_si128((__m128i *) (pu1_src)); ref_left = _mm_loadu_si128((__m128i *) (left_ptr)); ref_right = _mm_loadu_si128((__m128i *) (right_ptr)); ref_top = _mm_loadu_si128((__m128i *) (top_ptr)); ref_bot = _mm_loadu_si128((__m128i *) (bot_ptr)); sad_r0 = _mm_sad_epu8(src, ref_left); sad_r1 = _mm_sad_epu8(src, ref_right); sad_r2 = _mm_sad_epu8(src, ref_top); sad_r3 = _mm_sad_epu8(src, ref_bot); pu1_src += src_strd; left_ptr += ref_strd; right_ptr += ref_strd; top_ptr += ref_strd; bot_ptr += ref_strd; // Row 1 sad calculation src = _mm_loadu_si128((__m128i *) (pu1_src)); ref_left = _mm_loadu_si128((__m128i *) (left_ptr)); ref_right = _mm_loadu_si128((__m128i *) (right_ptr)); ref_top = _mm_loadu_si128((__m128i *) (top_ptr)); ref_bot = _mm_loadu_si128((__m128i *) (bot_ptr)); res_r0 = _mm_sad_epu8(src, ref_left); res_r1 = _mm_sad_epu8(src, ref_right); res_r2 = _mm_sad_epu8(src, ref_top); res_r3 = _mm_sad_epu8(src, ref_bot); sad_r0 = _mm_add_epi64(sad_r0, res_r0); sad_r1 = _mm_add_epi64(sad_r1, res_r1); sad_r2 = _mm_add_epi64(sad_r2, res_r2); sad_r3 = _mm_add_epi64(sad_r3, res_r3); pu1_src += src_strd; left_ptr += ref_strd; right_ptr += ref_strd; top_ptr += ref_strd; bot_ptr += ref_strd; // Row 2 sad calculation src = _mm_loadu_si128((__m128i *) (pu1_src)); ref_left = _mm_loadu_si128((__m128i *) (left_ptr)); ref_right = _mm_loadu_si128((__m128i *) (right_ptr)); ref_top = _mm_loadu_si128((__m128i *) (top_ptr)); ref_bot = _mm_loadu_si128((__m128i *) (bot_ptr)); res_r0 = _mm_sad_epu8(src, ref_left); res_r1 = _mm_sad_epu8(src, ref_right); res_r2 = _mm_sad_epu8(src, ref_top); res_r3 = _mm_sad_epu8(src, ref_bot); sad_r0 = _mm_add_epi64(sad_r0, res_r0); sad_r1 = _mm_add_epi64(sad_r1, res_r1); sad_r2 = _mm_add_epi64(sad_r2, res_r2); sad_r3 = _mm_add_epi64(sad_r3, res_r3); pu1_src += src_strd; left_ptr += ref_strd; right_ptr += ref_strd; top_ptr += ref_strd; bot_ptr += ref_strd; // Row 3 sad calculation src = _mm_loadu_si128((__m128i *) (pu1_src)); ref_left = _mm_loadu_si128((__m128i *) (left_ptr)); ref_right = _mm_loadu_si128((__m128i *) (right_ptr)); ref_top = _mm_loadu_si128((__m128i *) (top_ptr)); ref_bot = _mm_loadu_si128((__m128i *) (bot_ptr)); res_r0 = _mm_sad_epu8(src, ref_left); res_r1 = _mm_sad_epu8(src, ref_right); res_r2 = _mm_sad_epu8(src, ref_top); res_r3 = _mm_sad_epu8(src, ref_bot); sad_r0 = _mm_add_epi64(sad_r0, res_r0); sad_r1 = _mm_add_epi64(sad_r1, res_r1); sad_r2 = _mm_add_epi64(sad_r2, res_r2); sad_r3 = _mm_add_epi64(sad_r3, res_r3); pu1_src += src_strd; left_ptr += ref_strd; right_ptr += ref_strd; top_ptr += ref_strd; bot_ptr += ref_strd; // Row 4 sad calculation src = _mm_loadu_si128((__m128i *) (pu1_src)); ref_left = _mm_loadu_si128((__m128i *) (left_ptr)); ref_right = _mm_loadu_si128((__m128i *) (right_ptr)); ref_top = _mm_loadu_si128((__m128i *) (top_ptr)); ref_bot = _mm_loadu_si128((__m128i *) (bot_ptr)); res_r0 = _mm_sad_epu8(src, ref_left); res_r1 = _mm_sad_epu8(src, ref_right); res_r2 = _mm_sad_epu8(src, ref_top); res_r3 = _mm_sad_epu8(src, ref_bot); sad_r0 = _mm_add_epi64(sad_r0, res_r0); sad_r1 = _mm_add_epi64(sad_r1, res_r1); sad_r2 = _mm_add_epi64(sad_r2, res_r2); sad_r3 = _mm_add_epi64(sad_r3, res_r3); pu1_src += src_strd; left_ptr += ref_strd; right_ptr += ref_strd; top_ptr += ref_strd; bot_ptr += ref_strd; // Row 5 sad calculation src = _mm_loadu_si128((__m128i *) (pu1_src)); ref_left = _mm_loadu_si128((__m128i *) (left_ptr)); ref_right = _mm_loadu_si128((__m128i *) (right_ptr)); ref_top = _mm_loadu_si128((__m128i *) (top_ptr)); ref_bot = _mm_loadu_si128((__m128i *) (bot_ptr)); res_r0 = _mm_sad_epu8(src, ref_left); res_r1 = _mm_sad_epu8(src, ref_right); res_r2 = _mm_sad_epu8(src, ref_top); res_r3 = _mm_sad_epu8(src, ref_bot); sad_r0 = _mm_add_epi64(sad_r0, res_r0); sad_r1 = _mm_add_epi64(sad_r1, res_r1); sad_r2 = _mm_add_epi64(sad_r2, res_r2); sad_r3 = _mm_add_epi64(sad_r3, res_r3); pu1_src += src_strd; left_ptr += ref_strd; right_ptr += ref_strd; top_ptr += ref_strd; bot_ptr += ref_strd; // Row 6 sad calculation src = _mm_loadu_si128((__m128i *) (pu1_src)); ref_left = _mm_loadu_si128((__m128i *) (left_ptr)); ref_right = _mm_loadu_si128((__m128i *) (right_ptr)); ref_top = _mm_loadu_si128((__m128i *) (top_ptr)); ref_bot = _mm_loadu_si128((__m128i *) (bot_ptr)); res_r0 = _mm_sad_epu8(src, ref_left); res_r1 = _mm_sad_epu8(src, ref_right); res_r2 = _mm_sad_epu8(src, ref_top); res_r3 = _mm_sad_epu8(src, ref_bot); sad_r0 = _mm_add_epi64(sad_r0, res_r0); sad_r1 = _mm_add_epi64(sad_r1, res_r1); sad_r2 = _mm_add_epi64(sad_r2, res_r2); sad_r3 = _mm_add_epi64(sad_r3, res_r3); pu1_src += src_strd; left_ptr += ref_strd; right_ptr += ref_strd; top_ptr += ref_strd; bot_ptr += ref_strd; // Row 7 sad calculation src = _mm_loadu_si128((__m128i *) (pu1_src)); ref_left = _mm_loadu_si128((__m128i *) (left_ptr)); ref_right = _mm_loadu_si128((__m128i *) (right_ptr)); ref_top = _mm_loadu_si128((__m128i *) (top_ptr)); ref_bot = _mm_loadu_si128((__m128i *) (bot_ptr)); res_r0 = _mm_sad_epu8(src, ref_left); res_r1 = _mm_sad_epu8(src, ref_right); res_r2 = _mm_sad_epu8(src, ref_top); res_r3 = _mm_sad_epu8(src, ref_bot); sad_r0 = _mm_add_epi64(sad_r0, res_r0); sad_r1 = _mm_add_epi64(sad_r1, res_r1); sad_r2 = _mm_add_epi64(sad_r2, res_r2); sad_r3 = _mm_add_epi64(sad_r3, res_r3); pu1_src += src_strd; left_ptr += ref_strd; right_ptr += ref_strd; top_ptr += ref_strd; bot_ptr += ref_strd; // Row 8 sad calculation src = _mm_loadu_si128((__m128i *) (pu1_src)); ref_left = _mm_loadu_si128((__m128i *) (left_ptr)); ref_right = _mm_loadu_si128((__m128i *) (right_ptr)); ref_top = _mm_loadu_si128((__m128i *) (top_ptr)); ref_bot = _mm_loadu_si128((__m128i *) (bot_ptr)); res_r0 = _mm_sad_epu8(src, ref_left); res_r1 = _mm_sad_epu8(src, ref_right); res_r2 = _mm_sad_epu8(src, ref_top); res_r3 = _mm_sad_epu8(src, ref_bot); sad_r0 = _mm_add_epi64(sad_r0, res_r0); sad_r1 = _mm_add_epi64(sad_r1, res_r1); sad_r2 = _mm_add_epi64(sad_r2, res_r2); sad_r3 = _mm_add_epi64(sad_r3, res_r3); pu1_src += src_strd; left_ptr += ref_strd; right_ptr += ref_strd; top_ptr += ref_strd; bot_ptr += ref_strd; // Row 9 sad calculation src = _mm_loadu_si128((__m128i *) (pu1_src)); ref_left = _mm_loadu_si128((__m128i *) (left_ptr)); ref_right = _mm_loadu_si128((__m128i *) (right_ptr)); ref_top = _mm_loadu_si128((__m128i *) (top_ptr)); ref_bot = _mm_loadu_si128((__m128i *) (bot_ptr)); res_r0 = _mm_sad_epu8(src, ref_left); res_r1 = _mm_sad_epu8(src, ref_right); res_r2 = _mm_sad_epu8(src, ref_top); res_r3 = _mm_sad_epu8(src, ref_bot); sad_r0 = _mm_add_epi64(sad_r0, res_r0); sad_r1 = _mm_add_epi64(sad_r1, res_r1); sad_r2 = _mm_add_epi64(sad_r2, res_r2); sad_r3 = _mm_add_epi64(sad_r3, res_r3); pu1_src += src_strd; left_ptr += ref_strd; right_ptr += ref_strd; top_ptr += ref_strd; bot_ptr += ref_strd; // Row 10 sad calculation src = _mm_loadu_si128((__m128i *) (pu1_src)); ref_left = _mm_loadu_si128((__m128i *) (left_ptr)); ref_right = _mm_loadu_si128((__m128i *) (right_ptr)); ref_top = _mm_loadu_si128((__m128i *) (top_ptr)); ref_bot = _mm_loadu_si128((__m128i *) (bot_ptr)); res_r0 = _mm_sad_epu8(src, ref_left); res_r1 = _mm_sad_epu8(src, ref_right); res_r2 = _mm_sad_epu8(src, ref_top); res_r3 = _mm_sad_epu8(src, ref_bot); sad_r0 = _mm_add_epi64(sad_r0, res_r0); sad_r1 = _mm_add_epi64(sad_r1, res_r1); sad_r2 = _mm_add_epi64(sad_r2, res_r2); sad_r3 = _mm_add_epi64(sad_r3, res_r3); pu1_src += src_strd; left_ptr += ref_strd; right_ptr += ref_strd; top_ptr += ref_strd; bot_ptr += ref_strd; // Row 11 sad calculation src = _mm_loadu_si128((__m128i *) (pu1_src)); ref_left = _mm_loadu_si128((__m128i *) (left_ptr)); ref_right = _mm_loadu_si128((__m128i *) (right_ptr)); ref_top = _mm_loadu_si128((__m128i *) (top_ptr)); ref_bot = _mm_loadu_si128((__m128i *) (bot_ptr)); res_r0 = _mm_sad_epu8(src, ref_left); res_r1 = _mm_sad_epu8(src, ref_right); res_r2 = _mm_sad_epu8(src, ref_top); res_r3 = _mm_sad_epu8(src, ref_bot); sad_r0 = _mm_add_epi64(sad_r0, res_r0); sad_r1 = _mm_add_epi64(sad_r1, res_r1); sad_r2 = _mm_add_epi64(sad_r2, res_r2); sad_r3 = _mm_add_epi64(sad_r3, res_r3); pu1_src += src_strd; left_ptr += ref_strd; right_ptr += ref_strd; top_ptr += ref_strd; bot_ptr += ref_strd; // Row 12 sad calculation src = _mm_loadu_si128((__m128i *) (pu1_src)); ref_left = _mm_loadu_si128((__m128i *) (left_ptr)); ref_right = _mm_loadu_si128((__m128i *) (right_ptr)); ref_top = _mm_loadu_si128((__m128i *) (top_ptr)); ref_bot = _mm_loadu_si128((__m128i *) (bot_ptr)); res_r0 = _mm_sad_epu8(src, ref_left); res_r1 = _mm_sad_epu8(src, ref_right); res_r2 = _mm_sad_epu8(src, ref_top); res_r3 = _mm_sad_epu8(src, ref_bot); sad_r0 = _mm_add_epi64(sad_r0, res_r0); sad_r1 = _mm_add_epi64(sad_r1, res_r1); sad_r2 = _mm_add_epi64(sad_r2, res_r2); sad_r3 = _mm_add_epi64(sad_r3, res_r3); pu1_src += src_strd; left_ptr += ref_strd; right_ptr += ref_strd; top_ptr += ref_strd; bot_ptr += ref_strd; // Row 13 sad calculation src = _mm_loadu_si128((__m128i *) (pu1_src)); ref_left = _mm_loadu_si128((__m128i *) (left_ptr)); ref_right = _mm_loadu_si128((__m128i *) (right_ptr)); ref_top = _mm_loadu_si128((__m128i *) (top_ptr)); ref_bot = _mm_loadu_si128((__m128i *) (bot_ptr)); res_r0 = _mm_sad_epu8(src, ref_left); res_r1 = _mm_sad_epu8(src, ref_right); res_r2 = _mm_sad_epu8(src, ref_top); res_r3 = _mm_sad_epu8(src, ref_bot); sad_r0 = _mm_add_epi64(sad_r0, res_r0); sad_r1 = _mm_add_epi64(sad_r1, res_r1); sad_r2 = _mm_add_epi64(sad_r2, res_r2); sad_r3 = _mm_add_epi64(sad_r3, res_r3); pu1_src += src_strd; left_ptr += ref_strd; right_ptr += ref_strd; top_ptr += ref_strd; bot_ptr += ref_strd; // Row 14 sad calculation src = _mm_loadu_si128((__m128i *) (pu1_src)); ref_left = _mm_loadu_si128((__m128i *) (left_ptr)); ref_right = _mm_loadu_si128((__m128i *) (right_ptr)); ref_top = _mm_loadu_si128((__m128i *) (top_ptr)); ref_bot = _mm_loadu_si128((__m128i *) (bot_ptr)); res_r0 = _mm_sad_epu8(src, ref_left); res_r1 = _mm_sad_epu8(src, ref_right); res_r2 = _mm_sad_epu8(src, ref_top); res_r3 = _mm_sad_epu8(src, ref_bot); sad_r0 = _mm_add_epi64(sad_r0, res_r0); sad_r1 = _mm_add_epi64(sad_r1, res_r1); sad_r2 = _mm_add_epi64(sad_r2, res_r2); sad_r3 = _mm_add_epi64(sad_r3, res_r3); pu1_src += src_strd; left_ptr += ref_strd; right_ptr += ref_strd; top_ptr += ref_strd; bot_ptr += ref_strd; // Row 15 sad calculation src = _mm_loadu_si128((__m128i *) (pu1_src)); ref_left = _mm_loadu_si128((__m128i *) (left_ptr)); ref_right = _mm_loadu_si128((__m128i *) (right_ptr)); ref_top = _mm_loadu_si128((__m128i *) (top_ptr)); ref_bot = _mm_loadu_si128((__m128i *) (bot_ptr)); res_r0 = _mm_sad_epu8(src, ref_left); res_r1 = _mm_sad_epu8(src, ref_right); res_r2 = _mm_sad_epu8(src, ref_top); res_r3 = _mm_sad_epu8(src, ref_bot); sad_r0 = _mm_add_epi64(sad_r0, res_r0); sad_r1 = _mm_add_epi64(sad_r1, res_r1); sad_r2 = _mm_add_epi64(sad_r2, res_r2); sad_r3 = _mm_add_epi64(sad_r3, res_r3); val1 = _mm_extract_epi32(sad_r0, 0); val2 = _mm_extract_epi32(sad_r0, 2); pi4_sad[0] = (val1 + val2); val1 = _mm_extract_epi32(sad_r1, 0); val2 = _mm_extract_epi32(sad_r1, 2); pi4_sad[1] = (val1 + val2); val1 = _mm_extract_epi32(sad_r2, 0); val2 = _mm_extract_epi32(sad_r2, 2); pi4_sad[2] = (val1 + val2); val1 = _mm_extract_epi32(sad_r3, 0); val2 = _mm_extract_epi32(sad_r3, 2); pi4_sad[3] = (val1 + val2); } /** ****************************************************************************** * * @brief computes distortion (SAD) at all subpel points about the src location * * @par Description * This functions computes SAD at all points at a subpel distance from the * current source location. * * @param[in] pu1_src * UWORD8 pointer to the source * * @param[out] pu1_ref_half_x * UWORD8 pointer to half pel buffer * * @param[out] pu1_ref_half_y * UWORD8 pointer to half pel buffer * * @param[out] pu1_ref_half_xy * UWORD8 pointer to half pel buffer * * @param[in] src_strd * integer source stride * * @param[in] ref_strd * integer ref stride * * @param[out] pi4_sad * integer evaluated sad * pi4_sad[0] - half x * pi4_sad[1] - half x - 1 * pi4_sad[2] - half y * pi4_sad[3] - half y - 1 * pi4_sad[4] - half xy * pi4_sad[5] - half xy - 1 * pi4_sad[6] - half xy - strd * pi4_sad[7] - half xy - 1 - strd * * @remarks * ****************************************************************************** */ void ime_sub_pel_compute_sad_16x16_sse42(UWORD8 *pu1_src, UWORD8 *pu1_ref_half_x, UWORD8 *pu1_ref_half_y, UWORD8 *pu1_ref_half_xy, WORD32 src_strd, WORD32 ref_strd, WORD32 *pi4_sad) { UWORD8 *pu1_ref_half_x_left = pu1_ref_half_x - 1; UWORD8 *pu1_ref_half_y_top = pu1_ref_half_y - ref_strd; UWORD8 *pu1_ref_half_xy_left = pu1_ref_half_xy - 1; UWORD8 *pu1_ref_half_xy_top = pu1_ref_half_xy - ref_strd; UWORD8 *pu1_ref_half_xy_top_left = pu1_ref_half_xy - ref_strd - 1; WORD32 val1, val2; __m128i src, ref_half_x, ref_half_y, ref_half_xy; __m128i ref_half_x_left, ref_half_y_top, ref_half_xy_left, ref_half_xy_top, ref_half_xy_top_left; __m128i res_r0, res_r1, res_r2, res_r3, res_r4, res_r5, res_r6, res_r7; __m128i sad_r0, sad_r1, sad_r2, sad_r3, sad_r4, sad_r5, sad_r6, sad_r7; // Row 0 sad calculation src = _mm_loadu_si128((__m128i *) (pu1_src)); ref_half_x = _mm_loadu_si128((__m128i *) (pu1_ref_half_x)); ref_half_y = _mm_loadu_si128((__m128i *) (pu1_ref_half_y)); ref_half_xy = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy)); ref_half_x_left = _mm_loadu_si128((__m128i *) (pu1_ref_half_x_left)); ref_half_y_top = _mm_loadu_si128((__m128i *) (pu1_ref_half_y_top)); ref_half_xy_left = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy_left)); ref_half_xy_top = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy_top)); ref_half_xy_top_left = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy_top_left)); sad_r0 = _mm_sad_epu8(src, ref_half_x); sad_r1 = _mm_sad_epu8(src, ref_half_x_left); sad_r2 = _mm_sad_epu8(src, ref_half_y); sad_r3 = _mm_sad_epu8(src, ref_half_y_top); sad_r4 = _mm_sad_epu8(src, ref_half_xy); sad_r5 = _mm_sad_epu8(src, ref_half_xy_left); sad_r6 = _mm_sad_epu8(src, ref_half_xy_top); sad_r7 = _mm_sad_epu8(src, ref_half_xy_top_left); pu1_src += src_strd; pu1_ref_half_x += ref_strd; pu1_ref_half_x_left += ref_strd; pu1_ref_half_y += ref_strd; pu1_ref_half_y_top += ref_strd; pu1_ref_half_xy += ref_strd; pu1_ref_half_xy_left += ref_strd; pu1_ref_half_xy_top += ref_strd; pu1_ref_half_xy_top_left += ref_strd; // Row 1 sad calculation src = _mm_loadu_si128((__m128i *) (pu1_src)); ref_half_x = _mm_loadu_si128((__m128i *) (pu1_ref_half_x)); ref_half_y = _mm_loadu_si128((__m128i *) (pu1_ref_half_y)); ref_half_xy = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy)); ref_half_x_left = _mm_loadu_si128((__m128i *) (pu1_ref_half_x_left)); ref_half_y_top = _mm_loadu_si128((__m128i *) (pu1_ref_half_y_top)); ref_half_xy_left = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy_left)); ref_half_xy_top = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy_top)); ref_half_xy_top_left = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy_top_left)); res_r0 = _mm_sad_epu8(src, ref_half_x); res_r1 = _mm_sad_epu8(src, ref_half_x_left); res_r2 = _mm_sad_epu8(src, ref_half_y); res_r3 = _mm_sad_epu8(src, ref_half_y_top); res_r4 = _mm_sad_epu8(src, ref_half_xy); res_r5 = _mm_sad_epu8(src, ref_half_xy_left); res_r6 = _mm_sad_epu8(src, ref_half_xy_top); res_r7 = _mm_sad_epu8(src, ref_half_xy_top_left); sad_r0 = _mm_add_epi64(sad_r0, res_r0); sad_r1 = _mm_add_epi64(sad_r1, res_r1); sad_r2 = _mm_add_epi64(sad_r2, res_r2); sad_r3 = _mm_add_epi64(sad_r3, res_r3); sad_r4 = _mm_add_epi64(sad_r4, res_r4); sad_r5 = _mm_add_epi64(sad_r5, res_r5); sad_r6 = _mm_add_epi64(sad_r6, res_r6); sad_r7 = _mm_add_epi64(sad_r7, res_r7); pu1_src += src_strd; pu1_ref_half_x += ref_strd; pu1_ref_half_x_left += ref_strd; pu1_ref_half_y += ref_strd; pu1_ref_half_y_top += ref_strd; pu1_ref_half_xy += ref_strd; pu1_ref_half_xy_left += ref_strd; pu1_ref_half_xy_top += ref_strd; pu1_ref_half_xy_top_left += ref_strd; // Row 2 sad calculation src = _mm_loadu_si128((__m128i *) (pu1_src)); ref_half_x = _mm_loadu_si128((__m128i *) (pu1_ref_half_x)); ref_half_y = _mm_loadu_si128((__m128i *) (pu1_ref_half_y)); ref_half_xy = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy)); ref_half_x_left = _mm_loadu_si128((__m128i *) (pu1_ref_half_x_left)); ref_half_y_top = _mm_loadu_si128((__m128i *) (pu1_ref_half_y_top)); ref_half_xy_left = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy_left)); ref_half_xy_top = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy_top)); ref_half_xy_top_left = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy_top_left)); res_r0 = _mm_sad_epu8(src, ref_half_x); res_r1 = _mm_sad_epu8(src, ref_half_x_left); res_r2 = _mm_sad_epu8(src, ref_half_y); res_r3 = _mm_sad_epu8(src, ref_half_y_top); res_r4 = _mm_sad_epu8(src, ref_half_xy); res_r5 = _mm_sad_epu8(src, ref_half_xy_left); res_r6 = _mm_sad_epu8(src, ref_half_xy_top); res_r7 = _mm_sad_epu8(src, ref_half_xy_top_left); sad_r0 = _mm_add_epi64(sad_r0, res_r0); sad_r1 = _mm_add_epi64(sad_r1, res_r1); sad_r2 = _mm_add_epi64(sad_r2, res_r2); sad_r3 = _mm_add_epi64(sad_r3, res_r3); sad_r4 = _mm_add_epi64(sad_r4, res_r4); sad_r5 = _mm_add_epi64(sad_r5, res_r5); sad_r6 = _mm_add_epi64(sad_r6, res_r6); sad_r7 = _mm_add_epi64(sad_r7, res_r7); pu1_src += src_strd; pu1_ref_half_x += ref_strd; pu1_ref_half_x_left += ref_strd; pu1_ref_half_y += ref_strd; pu1_ref_half_y_top += ref_strd; pu1_ref_half_xy += ref_strd; pu1_ref_half_xy_left += ref_strd; pu1_ref_half_xy_top += ref_strd; pu1_ref_half_xy_top_left += ref_strd; // Row 3 sad calculation src = _mm_loadu_si128((__m128i *) (pu1_src)); ref_half_x = _mm_loadu_si128((__m128i *) (pu1_ref_half_x)); ref_half_y = _mm_loadu_si128((__m128i *) (pu1_ref_half_y)); ref_half_xy = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy)); ref_half_x_left = _mm_loadu_si128((__m128i *) (pu1_ref_half_x_left)); ref_half_y_top = _mm_loadu_si128((__m128i *) (pu1_ref_half_y_top)); ref_half_xy_left = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy_left)); ref_half_xy_top = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy_top)); ref_half_xy_top_left = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy_top_left)); res_r0 = _mm_sad_epu8(src, ref_half_x); res_r1 = _mm_sad_epu8(src, ref_half_x_left); res_r2 = _mm_sad_epu8(src, ref_half_y); res_r3 = _mm_sad_epu8(src, ref_half_y_top); res_r4 = _mm_sad_epu8(src, ref_half_xy); res_r5 = _mm_sad_epu8(src, ref_half_xy_left); res_r6 = _mm_sad_epu8(src, ref_half_xy_top); res_r7 = _mm_sad_epu8(src, ref_half_xy_top_left); sad_r0 = _mm_add_epi64(sad_r0, res_r0); sad_r1 = _mm_add_epi64(sad_r1, res_r1); sad_r2 = _mm_add_epi64(sad_r2, res_r2); sad_r3 = _mm_add_epi64(sad_r3, res_r3); sad_r4 = _mm_add_epi64(sad_r4, res_r4); sad_r5 = _mm_add_epi64(sad_r5, res_r5); sad_r6 = _mm_add_epi64(sad_r6, res_r6); sad_r7 = _mm_add_epi64(sad_r7, res_r7); pu1_src += src_strd; pu1_ref_half_x += ref_strd; pu1_ref_half_x_left += ref_strd; pu1_ref_half_y += ref_strd; pu1_ref_half_y_top += ref_strd; pu1_ref_half_xy += ref_strd; pu1_ref_half_xy_left += ref_strd; pu1_ref_half_xy_top += ref_strd; pu1_ref_half_xy_top_left += ref_strd; // Row 4 sad calculation src = _mm_loadu_si128((__m128i *) (pu1_src)); ref_half_x = _mm_loadu_si128((__m128i *) (pu1_ref_half_x)); ref_half_y = _mm_loadu_si128((__m128i *) (pu1_ref_half_y)); ref_half_xy = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy)); ref_half_x_left = _mm_loadu_si128((__m128i *) (pu1_ref_half_x_left)); ref_half_y_top = _mm_loadu_si128((__m128i *) (pu1_ref_half_y_top)); ref_half_xy_left = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy_left)); ref_half_xy_top = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy_top)); ref_half_xy_top_left = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy_top_left)); res_r0 = _mm_sad_epu8(src, ref_half_x); res_r1 = _mm_sad_epu8(src, ref_half_x_left); res_r2 = _mm_sad_epu8(src, ref_half_y); res_r3 = _mm_sad_epu8(src, ref_half_y_top); res_r4 = _mm_sad_epu8(src, ref_half_xy); res_r5 = _mm_sad_epu8(src, ref_half_xy_left); res_r6 = _mm_sad_epu8(src, ref_half_xy_top); res_r7 = _mm_sad_epu8(src, ref_half_xy_top_left); sad_r0 = _mm_add_epi64(sad_r0, res_r0); sad_r1 = _mm_add_epi64(sad_r1, res_r1); sad_r2 = _mm_add_epi64(sad_r2, res_r2); sad_r3 = _mm_add_epi64(sad_r3, res_r3); sad_r4 = _mm_add_epi64(sad_r4, res_r4); sad_r5 = _mm_add_epi64(sad_r5, res_r5); sad_r6 = _mm_add_epi64(sad_r6, res_r6); sad_r7 = _mm_add_epi64(sad_r7, res_r7); pu1_src += src_strd; pu1_ref_half_x += ref_strd; pu1_ref_half_x_left += ref_strd; pu1_ref_half_y += ref_strd; pu1_ref_half_y_top += ref_strd; pu1_ref_half_xy += ref_strd; pu1_ref_half_xy_left += ref_strd; pu1_ref_half_xy_top += ref_strd; pu1_ref_half_xy_top_left += ref_strd; // Row 5 sad calculation src = _mm_loadu_si128((__m128i *) (pu1_src)); ref_half_x = _mm_loadu_si128((__m128i *) (pu1_ref_half_x)); ref_half_y = _mm_loadu_si128((__m128i *) (pu1_ref_half_y)); ref_half_xy = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy)); ref_half_x_left = _mm_loadu_si128((__m128i *) (pu1_ref_half_x_left)); ref_half_y_top = _mm_loadu_si128((__m128i *) (pu1_ref_half_y_top)); ref_half_xy_left = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy_left)); ref_half_xy_top = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy_top)); ref_half_xy_top_left = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy_top_left)); res_r0 = _mm_sad_epu8(src, ref_half_x); res_r1 = _mm_sad_epu8(src, ref_half_x_left); res_r2 = _mm_sad_epu8(src, ref_half_y); res_r3 = _mm_sad_epu8(src, ref_half_y_top); res_r4 = _mm_sad_epu8(src, ref_half_xy); res_r5 = _mm_sad_epu8(src, ref_half_xy_left); res_r6 = _mm_sad_epu8(src, ref_half_xy_top); res_r7 = _mm_sad_epu8(src, ref_half_xy_top_left); sad_r0 = _mm_add_epi64(sad_r0, res_r0); sad_r1 = _mm_add_epi64(sad_r1, res_r1); sad_r2 = _mm_add_epi64(sad_r2, res_r2); sad_r3 = _mm_add_epi64(sad_r3, res_r3); sad_r4 = _mm_add_epi64(sad_r4, res_r4); sad_r5 = _mm_add_epi64(sad_r5, res_r5); sad_r6 = _mm_add_epi64(sad_r6, res_r6); sad_r7 = _mm_add_epi64(sad_r7, res_r7); pu1_src += src_strd; pu1_ref_half_x += ref_strd; pu1_ref_half_x_left += ref_strd; pu1_ref_half_y += ref_strd; pu1_ref_half_y_top += ref_strd; pu1_ref_half_xy += ref_strd; pu1_ref_half_xy_left += ref_strd; pu1_ref_half_xy_top += ref_strd; pu1_ref_half_xy_top_left += ref_strd; // Row 6 sad calculation src = _mm_loadu_si128((__m128i *) (pu1_src)); ref_half_x = _mm_loadu_si128((__m128i *) (pu1_ref_half_x)); ref_half_y = _mm_loadu_si128((__m128i *) (pu1_ref_half_y)); ref_half_xy = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy)); ref_half_x_left = _mm_loadu_si128((__m128i *) (pu1_ref_half_x_left)); ref_half_y_top = _mm_loadu_si128((__m128i *) (pu1_ref_half_y_top)); ref_half_xy_left = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy_left)); ref_half_xy_top = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy_top)); ref_half_xy_top_left = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy_top_left)); res_r0 = _mm_sad_epu8(src, ref_half_x); res_r1 = _mm_sad_epu8(src, ref_half_x_left); res_r2 = _mm_sad_epu8(src, ref_half_y); res_r3 = _mm_sad_epu8(src, ref_half_y_top); res_r4 = _mm_sad_epu8(src, ref_half_xy); res_r5 = _mm_sad_epu8(src, ref_half_xy_left); res_r6 = _mm_sad_epu8(src, ref_half_xy_top); res_r7 = _mm_sad_epu8(src, ref_half_xy_top_left); sad_r0 = _mm_add_epi64(sad_r0, res_r0); sad_r1 = _mm_add_epi64(sad_r1, res_r1); sad_r2 = _mm_add_epi64(sad_r2, res_r2); sad_r3 = _mm_add_epi64(sad_r3, res_r3); sad_r4 = _mm_add_epi64(sad_r4, res_r4); sad_r5 = _mm_add_epi64(sad_r5, res_r5); sad_r6 = _mm_add_epi64(sad_r6, res_r6); sad_r7 = _mm_add_epi64(sad_r7, res_r7); pu1_src += src_strd; pu1_ref_half_x += ref_strd; pu1_ref_half_x_left += ref_strd; pu1_ref_half_y += ref_strd; pu1_ref_half_y_top += ref_strd; pu1_ref_half_xy += ref_strd; pu1_ref_half_xy_left += ref_strd; pu1_ref_half_xy_top += ref_strd; pu1_ref_half_xy_top_left += ref_strd; // Row 7 sad calculation src = _mm_loadu_si128((__m128i *) (pu1_src)); ref_half_x = _mm_loadu_si128((__m128i *) (pu1_ref_half_x)); ref_half_y = _mm_loadu_si128((__m128i *) (pu1_ref_half_y)); ref_half_xy = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy)); ref_half_x_left = _mm_loadu_si128((__m128i *) (pu1_ref_half_x_left)); ref_half_y_top = _mm_loadu_si128((__m128i *) (pu1_ref_half_y_top)); ref_half_xy_left = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy_left)); ref_half_xy_top = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy_top)); ref_half_xy_top_left = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy_top_left)); res_r0 = _mm_sad_epu8(src, ref_half_x); res_r1 = _mm_sad_epu8(src, ref_half_x_left); res_r2 = _mm_sad_epu8(src, ref_half_y); res_r3 = _mm_sad_epu8(src, ref_half_y_top); res_r4 = _mm_sad_epu8(src, ref_half_xy); res_r5 = _mm_sad_epu8(src, ref_half_xy_left); res_r6 = _mm_sad_epu8(src, ref_half_xy_top); res_r7 = _mm_sad_epu8(src, ref_half_xy_top_left); sad_r0 = _mm_add_epi64(sad_r0, res_r0); sad_r1 = _mm_add_epi64(sad_r1, res_r1); sad_r2 = _mm_add_epi64(sad_r2, res_r2); sad_r3 = _mm_add_epi64(sad_r3, res_r3); sad_r4 = _mm_add_epi64(sad_r4, res_r4); sad_r5 = _mm_add_epi64(sad_r5, res_r5); sad_r6 = _mm_add_epi64(sad_r6, res_r6); sad_r7 = _mm_add_epi64(sad_r7, res_r7); pu1_src += src_strd; pu1_ref_half_x += ref_strd; pu1_ref_half_x_left += ref_strd; pu1_ref_half_y += ref_strd; pu1_ref_half_y_top += ref_strd; pu1_ref_half_xy += ref_strd; pu1_ref_half_xy_left += ref_strd; pu1_ref_half_xy_top += ref_strd; pu1_ref_half_xy_top_left += ref_strd; // Row 8 sad calculation src = _mm_loadu_si128((__m128i *) (pu1_src)); ref_half_x = _mm_loadu_si128((__m128i *) (pu1_ref_half_x)); ref_half_y = _mm_loadu_si128((__m128i *) (pu1_ref_half_y)); ref_half_xy = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy)); ref_half_x_left = _mm_loadu_si128((__m128i *) (pu1_ref_half_x_left)); ref_half_y_top = _mm_loadu_si128((__m128i *) (pu1_ref_half_y_top)); ref_half_xy_left = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy_left)); ref_half_xy_top = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy_top)); ref_half_xy_top_left = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy_top_left)); res_r0 = _mm_sad_epu8(src, ref_half_x); res_r1 = _mm_sad_epu8(src, ref_half_x_left); res_r2 = _mm_sad_epu8(src, ref_half_y); res_r3 = _mm_sad_epu8(src, ref_half_y_top); res_r4 = _mm_sad_epu8(src, ref_half_xy); res_r5 = _mm_sad_epu8(src, ref_half_xy_left); res_r6 = _mm_sad_epu8(src, ref_half_xy_top); res_r7 = _mm_sad_epu8(src, ref_half_xy_top_left); sad_r0 = _mm_add_epi64(sad_r0, res_r0); sad_r1 = _mm_add_epi64(sad_r1, res_r1); sad_r2 = _mm_add_epi64(sad_r2, res_r2); sad_r3 = _mm_add_epi64(sad_r3, res_r3); sad_r4 = _mm_add_epi64(sad_r4, res_r4); sad_r5 = _mm_add_epi64(sad_r5, res_r5); sad_r6 = _mm_add_epi64(sad_r6, res_r6); sad_r7 = _mm_add_epi64(sad_r7, res_r7); pu1_src += src_strd; pu1_ref_half_x += ref_strd; pu1_ref_half_x_left += ref_strd; pu1_ref_half_y += ref_strd; pu1_ref_half_y_top += ref_strd; pu1_ref_half_xy += ref_strd; pu1_ref_half_xy_left += ref_strd; pu1_ref_half_xy_top += ref_strd; pu1_ref_half_xy_top_left += ref_strd; // Row 9 sad calculation src = _mm_loadu_si128((__m128i *) (pu1_src)); ref_half_x = _mm_loadu_si128((__m128i *) (pu1_ref_half_x)); ref_half_y = _mm_loadu_si128((__m128i *) (pu1_ref_half_y)); ref_half_xy = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy)); ref_half_x_left = _mm_loadu_si128((__m128i *) (pu1_ref_half_x_left)); ref_half_y_top = _mm_loadu_si128((__m128i *) (pu1_ref_half_y_top)); ref_half_xy_left = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy_left)); ref_half_xy_top = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy_top)); ref_half_xy_top_left = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy_top_left)); res_r0 = _mm_sad_epu8(src, ref_half_x); res_r1 = _mm_sad_epu8(src, ref_half_x_left); res_r2 = _mm_sad_epu8(src, ref_half_y); res_r3 = _mm_sad_epu8(src, ref_half_y_top); res_r4 = _mm_sad_epu8(src, ref_half_xy); res_r5 = _mm_sad_epu8(src, ref_half_xy_left); res_r6 = _mm_sad_epu8(src, ref_half_xy_top); res_r7 = _mm_sad_epu8(src, ref_half_xy_top_left); sad_r0 = _mm_add_epi64(sad_r0, res_r0); sad_r1 = _mm_add_epi64(sad_r1, res_r1); sad_r2 = _mm_add_epi64(sad_r2, res_r2); sad_r3 = _mm_add_epi64(sad_r3, res_r3); sad_r4 = _mm_add_epi64(sad_r4, res_r4); sad_r5 = _mm_add_epi64(sad_r5, res_r5); sad_r6 = _mm_add_epi64(sad_r6, res_r6); sad_r7 = _mm_add_epi64(sad_r7, res_r7); pu1_src += src_strd; pu1_ref_half_x += ref_strd; pu1_ref_half_x_left += ref_strd; pu1_ref_half_y += ref_strd; pu1_ref_half_y_top += ref_strd; pu1_ref_half_xy += ref_strd; pu1_ref_half_xy_left += ref_strd; pu1_ref_half_xy_top += ref_strd; pu1_ref_half_xy_top_left += ref_strd; // Row 10 sad calculation src = _mm_loadu_si128((__m128i *) (pu1_src)); ref_half_x = _mm_loadu_si128((__m128i *) (pu1_ref_half_x)); ref_half_y = _mm_loadu_si128((__m128i *) (pu1_ref_half_y)); ref_half_xy = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy)); ref_half_x_left = _mm_loadu_si128((__m128i *) (pu1_ref_half_x_left)); ref_half_y_top = _mm_loadu_si128((__m128i *) (pu1_ref_half_y_top)); ref_half_xy_left = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy_left)); ref_half_xy_top = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy_top)); ref_half_xy_top_left = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy_top_left)); res_r0 = _mm_sad_epu8(src, ref_half_x); res_r1 = _mm_sad_epu8(src, ref_half_x_left); res_r2 = _mm_sad_epu8(src, ref_half_y); res_r3 = _mm_sad_epu8(src, ref_half_y_top); res_r4 = _mm_sad_epu8(src, ref_half_xy); res_r5 = _mm_sad_epu8(src, ref_half_xy_left); res_r6 = _mm_sad_epu8(src, ref_half_xy_top); res_r7 = _mm_sad_epu8(src, ref_half_xy_top_left); sad_r0 = _mm_add_epi64(sad_r0, res_r0); sad_r1 = _mm_add_epi64(sad_r1, res_r1); sad_r2 = _mm_add_epi64(sad_r2, res_r2); sad_r3 = _mm_add_epi64(sad_r3, res_r3); sad_r4 = _mm_add_epi64(sad_r4, res_r4); sad_r5 = _mm_add_epi64(sad_r5, res_r5); sad_r6 = _mm_add_epi64(sad_r6, res_r6); sad_r7 = _mm_add_epi64(sad_r7, res_r7); pu1_src += src_strd; pu1_ref_half_x += ref_strd; pu1_ref_half_x_left += ref_strd; pu1_ref_half_y += ref_strd; pu1_ref_half_y_top += ref_strd; pu1_ref_half_xy += ref_strd; pu1_ref_half_xy_left += ref_strd; pu1_ref_half_xy_top += ref_strd; pu1_ref_half_xy_top_left += ref_strd; // Row 11 sad calculation src = _mm_loadu_si128((__m128i *) (pu1_src)); ref_half_x = _mm_loadu_si128((__m128i *) (pu1_ref_half_x)); ref_half_y = _mm_loadu_si128((__m128i *) (pu1_ref_half_y)); ref_half_xy = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy)); ref_half_x_left = _mm_loadu_si128((__m128i *) (pu1_ref_half_x_left)); ref_half_y_top = _mm_loadu_si128((__m128i *) (pu1_ref_half_y_top)); ref_half_xy_left = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy_left)); ref_half_xy_top = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy_top)); ref_half_xy_top_left = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy_top_left)); res_r0 = _mm_sad_epu8(src, ref_half_x); res_r1 = _mm_sad_epu8(src, ref_half_x_left); res_r2 = _mm_sad_epu8(src, ref_half_y); res_r3 = _mm_sad_epu8(src, ref_half_y_top); res_r4 = _mm_sad_epu8(src, ref_half_xy); res_r5 = _mm_sad_epu8(src, ref_half_xy_left); res_r6 = _mm_sad_epu8(src, ref_half_xy_top); res_r7 = _mm_sad_epu8(src, ref_half_xy_top_left); sad_r0 = _mm_add_epi64(sad_r0, res_r0); sad_r1 = _mm_add_epi64(sad_r1, res_r1); sad_r2 = _mm_add_epi64(sad_r2, res_r2); sad_r3 = _mm_add_epi64(sad_r3, res_r3); sad_r4 = _mm_add_epi64(sad_r4, res_r4); sad_r5 = _mm_add_epi64(sad_r5, res_r5); sad_r6 = _mm_add_epi64(sad_r6, res_r6); sad_r7 = _mm_add_epi64(sad_r7, res_r7); pu1_src += src_strd; pu1_ref_half_x += ref_strd; pu1_ref_half_x_left += ref_strd; pu1_ref_half_y += ref_strd; pu1_ref_half_y_top += ref_strd; pu1_ref_half_xy += ref_strd; pu1_ref_half_xy_left += ref_strd; pu1_ref_half_xy_top += ref_strd; pu1_ref_half_xy_top_left += ref_strd; // Row 12 sad calculation src = _mm_loadu_si128((__m128i *) (pu1_src)); ref_half_x = _mm_loadu_si128((__m128i *) (pu1_ref_half_x)); ref_half_y = _mm_loadu_si128((__m128i *) (pu1_ref_half_y)); ref_half_xy = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy)); ref_half_x_left = _mm_loadu_si128((__m128i *) (pu1_ref_half_x_left)); ref_half_y_top = _mm_loadu_si128((__m128i *) (pu1_ref_half_y_top)); ref_half_xy_left = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy_left)); ref_half_xy_top = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy_top)); ref_half_xy_top_left = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy_top_left)); res_r0 = _mm_sad_epu8(src, ref_half_x); res_r1 = _mm_sad_epu8(src, ref_half_x_left); res_r2 = _mm_sad_epu8(src, ref_half_y); res_r3 = _mm_sad_epu8(src, ref_half_y_top); res_r4 = _mm_sad_epu8(src, ref_half_xy); res_r5 = _mm_sad_epu8(src, ref_half_xy_left); res_r6 = _mm_sad_epu8(src, ref_half_xy_top); res_r7 = _mm_sad_epu8(src, ref_half_xy_top_left); sad_r0 = _mm_add_epi64(sad_r0, res_r0); sad_r1 = _mm_add_epi64(sad_r1, res_r1); sad_r2 = _mm_add_epi64(sad_r2, res_r2); sad_r3 = _mm_add_epi64(sad_r3, res_r3); sad_r4 = _mm_add_epi64(sad_r4, res_r4); sad_r5 = _mm_add_epi64(sad_r5, res_r5); sad_r6 = _mm_add_epi64(sad_r6, res_r6); sad_r7 = _mm_add_epi64(sad_r7, res_r7); pu1_src += src_strd; pu1_ref_half_x += ref_strd; pu1_ref_half_x_left += ref_strd; pu1_ref_half_y += ref_strd; pu1_ref_half_y_top += ref_strd; pu1_ref_half_xy += ref_strd; pu1_ref_half_xy_left += ref_strd; pu1_ref_half_xy_top += ref_strd; pu1_ref_half_xy_top_left += ref_strd; // Row 13 sad calculation src = _mm_loadu_si128((__m128i *) (pu1_src)); ref_half_x = _mm_loadu_si128((__m128i *) (pu1_ref_half_x)); ref_half_y = _mm_loadu_si128((__m128i *) (pu1_ref_half_y)); ref_half_xy = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy)); ref_half_x_left = _mm_loadu_si128((__m128i *) (pu1_ref_half_x_left)); ref_half_y_top = _mm_loadu_si128((__m128i *) (pu1_ref_half_y_top)); ref_half_xy_left = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy_left)); ref_half_xy_top = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy_top)); ref_half_xy_top_left = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy_top_left)); res_r0 = _mm_sad_epu8(src, ref_half_x); res_r1 = _mm_sad_epu8(src, ref_half_x_left); res_r2 = _mm_sad_epu8(src, ref_half_y); res_r3 = _mm_sad_epu8(src, ref_half_y_top); res_r4 = _mm_sad_epu8(src, ref_half_xy); res_r5 = _mm_sad_epu8(src, ref_half_xy_left); res_r6 = _mm_sad_epu8(src, ref_half_xy_top); res_r7 = _mm_sad_epu8(src, ref_half_xy_top_left); sad_r0 = _mm_add_epi64(sad_r0, res_r0); sad_r1 = _mm_add_epi64(sad_r1, res_r1); sad_r2 = _mm_add_epi64(sad_r2, res_r2); sad_r3 = _mm_add_epi64(sad_r3, res_r3); sad_r4 = _mm_add_epi64(sad_r4, res_r4); sad_r5 = _mm_add_epi64(sad_r5, res_r5); sad_r6 = _mm_add_epi64(sad_r6, res_r6); sad_r7 = _mm_add_epi64(sad_r7, res_r7); pu1_src += src_strd; pu1_ref_half_x += ref_strd; pu1_ref_half_x_left += ref_strd; pu1_ref_half_y += ref_strd; pu1_ref_half_y_top += ref_strd; pu1_ref_half_xy += ref_strd; pu1_ref_half_xy_left += ref_strd; pu1_ref_half_xy_top += ref_strd; pu1_ref_half_xy_top_left += ref_strd; // Row 14 sad calculation src = _mm_loadu_si128((__m128i *) (pu1_src)); ref_half_x = _mm_loadu_si128((__m128i *) (pu1_ref_half_x)); ref_half_y = _mm_loadu_si128((__m128i *) (pu1_ref_half_y)); ref_half_xy = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy)); ref_half_x_left = _mm_loadu_si128((__m128i *) (pu1_ref_half_x_left)); ref_half_y_top = _mm_loadu_si128((__m128i *) (pu1_ref_half_y_top)); ref_half_xy_left = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy_left)); ref_half_xy_top = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy_top)); ref_half_xy_top_left = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy_top_left)); res_r0 = _mm_sad_epu8(src, ref_half_x); res_r1 = _mm_sad_epu8(src, ref_half_x_left); res_r2 = _mm_sad_epu8(src, ref_half_y); res_r3 = _mm_sad_epu8(src, ref_half_y_top); res_r4 = _mm_sad_epu8(src, ref_half_xy); res_r5 = _mm_sad_epu8(src, ref_half_xy_left); res_r6 = _mm_sad_epu8(src, ref_half_xy_top); res_r7 = _mm_sad_epu8(src, ref_half_xy_top_left); sad_r0 = _mm_add_epi64(sad_r0, res_r0); sad_r1 = _mm_add_epi64(sad_r1, res_r1); sad_r2 = _mm_add_epi64(sad_r2, res_r2); sad_r3 = _mm_add_epi64(sad_r3, res_r3); sad_r4 = _mm_add_epi64(sad_r4, res_r4); sad_r5 = _mm_add_epi64(sad_r5, res_r5); sad_r6 = _mm_add_epi64(sad_r6, res_r6); sad_r7 = _mm_add_epi64(sad_r7, res_r7); pu1_src += src_strd; pu1_ref_half_x += ref_strd; pu1_ref_half_x_left += ref_strd; pu1_ref_half_y += ref_strd; pu1_ref_half_y_top += ref_strd; pu1_ref_half_xy += ref_strd; pu1_ref_half_xy_left += ref_strd; pu1_ref_half_xy_top += ref_strd; pu1_ref_half_xy_top_left += ref_strd; // Row 15 sad calculation src = _mm_loadu_si128((__m128i *) (pu1_src)); ref_half_x = _mm_loadu_si128((__m128i *) (pu1_ref_half_x)); ref_half_y = _mm_loadu_si128((__m128i *) (pu1_ref_half_y)); ref_half_xy = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy)); ref_half_x_left = _mm_loadu_si128((__m128i *) (pu1_ref_half_x_left)); ref_half_y_top = _mm_loadu_si128((__m128i *) (pu1_ref_half_y_top)); ref_half_xy_left = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy_left)); ref_half_xy_top = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy_top)); ref_half_xy_top_left = _mm_loadu_si128((__m128i *) (pu1_ref_half_xy_top_left)); res_r0 = _mm_sad_epu8(src, ref_half_x); res_r1 = _mm_sad_epu8(src, ref_half_x_left); res_r2 = _mm_sad_epu8(src, ref_half_y); res_r3 = _mm_sad_epu8(src, ref_half_y_top); res_r4 = _mm_sad_epu8(src, ref_half_xy); res_r5 = _mm_sad_epu8(src, ref_half_xy_left); res_r6 = _mm_sad_epu8(src, ref_half_xy_top); res_r7 = _mm_sad_epu8(src, ref_half_xy_top_left); sad_r0 = _mm_add_epi64(sad_r0, res_r0); sad_r1 = _mm_add_epi64(sad_r1, res_r1); sad_r2 = _mm_add_epi64(sad_r2, res_r2); sad_r3 = _mm_add_epi64(sad_r3, res_r3); sad_r4 = _mm_add_epi64(sad_r4, res_r4); sad_r5 = _mm_add_epi64(sad_r5, res_r5); sad_r6 = _mm_add_epi64(sad_r6, res_r6); sad_r7 = _mm_add_epi64(sad_r7, res_r7); val1 = _mm_extract_epi32(sad_r0, 0); val2 = _mm_extract_epi32(sad_r0, 2); pi4_sad[0] = (val1 + val2); val1 = _mm_extract_epi32(sad_r1, 0); val2 = _mm_extract_epi32(sad_r1, 2); pi4_sad[1] = (val1 + val2); val1 = _mm_extract_epi32(sad_r2, 0); val2 = _mm_extract_epi32(sad_r2, 2); pi4_sad[2] = (val1 + val2); val1 = _mm_extract_epi32(sad_r3, 0); val2 = _mm_extract_epi32(sad_r3, 2); pi4_sad[3] = (val1 + val2); val1 = _mm_extract_epi32(sad_r4, 0); val2 = _mm_extract_epi32(sad_r4, 2); pi4_sad[4] = (val1 + val2); val1 = _mm_extract_epi32(sad_r5, 0); val2 = _mm_extract_epi32(sad_r5, 2); pi4_sad[5] = (val1 + val2); val1 = _mm_extract_epi32(sad_r6, 0); val2 = _mm_extract_epi32(sad_r6, 2); pi4_sad[6] = (val1 + val2); val1 = _mm_extract_epi32(sad_r7, 0); val2 = _mm_extract_epi32(sad_r7, 2); pi4_sad[7] = (val1 + val2); return; } /* * * @brief This function computes SAD between two 16x16 blocks * It also computes if the block will be zero after H264 transform and quant for * Intra 16x16 blocks * * @param[in] pu1_src * UWORD8 pointer to the source * * @param[out] pu1_dst * UWORD8 pointer to the destination * * @param[in] src_strd * integer source stride * * @param[in] dst_strd * integer destination stride * * @param[in] pu2_thrsh * Threshold for each element of transofrmed quantized block * * @param[out] pi4_mb_distortion * integer evaluated sad * * @param[out] pu4_is_zero * Poitner to store if the block is zero after transform and quantization * * @remarks * ****************************************************************************** */ void ime_compute_satqd_16x16_lumainter_sse42(UWORD8 *pu1_src, UWORD8 *pu1_est, WORD32 src_strd, WORD32 est_strd, UWORD16 *pu2_thrsh, WORD32 *pi4_mb_distortion, UWORD32 *pu4_is_zero) { __m128i src_r0, src_r1, src_r2, src_r3; __m128i est_r0, est_r1, est_r2, est_r3; __m128i temp0, temp1, temp2, temp3, temp4; __m128i zero = _mm_setzero_si128(); // all bits reset to zero __m128i all_one = _mm_set1_epi8(0xFF); __m128i sad_b1, sad_b2, threshold; WORD16 sad_1, sad_2; WORD32 i; UWORD32 flag = 0; WORD32 test1, test2; threshold = _mm_loadu_si128((__m128i *) pu2_thrsh); (*pi4_mb_distortion) = 0; for (i=0; i<4; i++) { src_r0 = _mm_loadl_epi64((__m128i *) pu1_src); //Row 0 - Block1 and 2 src_r1 = _mm_loadl_epi64((__m128i *) (pu1_src + src_strd)); //Row 1 - Block1 and 2 src_r2 = _mm_loadl_epi64((__m128i *) (pu1_src + 2 * src_strd)); //Row 2 - Block1 and 2 src_r3 = _mm_loadl_epi64((__m128i *) (pu1_src + 3 * src_strd)); //Row 3 - Block1 and 2 src_r0 = _mm_cvtepu8_epi16(src_r0); src_r1 = _mm_cvtepu8_epi16(src_r1); src_r2 = _mm_cvtepu8_epi16(src_r2); src_r3 = _mm_cvtepu8_epi16(src_r3); est_r0 = _mm_loadl_epi64((__m128i *) pu1_est); est_r1 = _mm_loadl_epi64((__m128i *) (pu1_est + est_strd)); est_r2 = _mm_loadl_epi64((__m128i *) (pu1_est + 2 * est_strd)); est_r3 = _mm_loadl_epi64((__m128i *) (pu1_est + 3 * est_strd)); est_r0 = _mm_cvtepu8_epi16(est_r0); est_r1 = _mm_cvtepu8_epi16(est_r1); est_r2 = _mm_cvtepu8_epi16(est_r2); est_r3 = _mm_cvtepu8_epi16(est_r3); src_r0 = _mm_sub_epi16(src_r0, est_r0); src_r1 = _mm_sub_epi16(src_r1, est_r1); src_r2 = _mm_sub_epi16(src_r2, est_r2); src_r3 = _mm_sub_epi16(src_r3, est_r3); src_r0 = _mm_abs_epi16(src_r0); src_r1 = _mm_abs_epi16(src_r1); src_r2 = _mm_abs_epi16(src_r2); src_r3 = _mm_abs_epi16(src_r3); src_r0 = _mm_add_epi16(src_r0, src_r3); //s1 s4 s4 s1 a1 a4 a4 a1 src_r1 = _mm_add_epi16(src_r1, src_r2); //s2 s3 s3 s2 a2 a3 a3 a2 //SAD calculation temp0 = _mm_add_epi16(src_r0, src_r1); //s1+s2 s4+s3 s4+s3 s1+s2 a1+a2 a4+a3 a4+a3 a1+a2 temp0 = _mm_hadd_epi16(temp0, zero); temp0 = _mm_hadd_epi16(temp0, zero); //sad1, sad2 - 16bit values sad_1 = _mm_extract_epi16(temp0, 0); sad_2 = _mm_extract_epi16(temp0, 1); (*pi4_mb_distortion) += sad_1 + sad_2; if (flag == 0) { sad_b1 = _mm_set1_epi16((sad_1 << 1)); sad_b2 = _mm_set1_epi16((sad_2 << 1)); src_r0 = _mm_shufflelo_epi16(src_r0, 0x9c); //Block 0 s1 s1 s4 s4 a1 a4 a4 a1 src_r0 = _mm_shufflehi_epi16(src_r0, 0x9c); //Block 1 s1 s1 s4 s4 a1 a1 a4 a4 src_r1 = _mm_shufflelo_epi16(src_r1, 0x9c); //Block 0 s2 s2 s3 s3 a2 a3 a3 a2 src_r1 = _mm_shufflehi_epi16(src_r1, 0x9c); //Block 1 s2 s2 s3 s3 a2 a2 a3 a3 src_r0 = _mm_hadd_epi16(src_r0, zero); //s1 s4 a1 a4 0 0 0 0 src_r1 = _mm_hadd_epi16(src_r1, zero); //s2 s3 a2 a3 0 0 0 0 temp0 = _mm_slli_epi16(src_r0, 1);//s1<<1 s4<<1 a1<<1 a4<<1 0 0 0 0 temp1 = _mm_slli_epi16(src_r1, 1);//s2<<1 s3<<1 a2<<1 a3<<1 0 0 0 0 temp0 = _mm_shufflelo_epi16(temp0, 0xb1);//s4<<1 s1<<1 a4<<1 a1<<1 0 0 0 0 temp1 = _mm_shufflelo_epi16(temp1, 0xb1);//s3<<1 s2<<1 a3<<1 a2<<1 0 0 0 0 temp2 = _mm_sub_epi16(src_r0, temp1);//(s1-s3<<1) (s4-s2<<1) (a1-a3<<1) (a4-a2<<1) 0 0 0 0 temp3 = _mm_sub_epi16(src_r1, temp0);//(s2-s4<<1) (s3-s1<<1) (a2-a4<<1) (a3-a1<<1) 0 0 0 0 temp4 = _mm_add_epi16(src_r0, src_r1);//s1+s2 s4+s3 a1+a2 a4+a3 0 0 0 0 temp0 = _mm_hadd_epi16(src_r0, zero); //s1+s4 a1+a4 0 0 0 0 0 0 temp1 = _mm_hadd_epi16(src_r1, zero); //s2+s3 a2+a3 0 0 0 0 0 0 temp0 = _mm_unpacklo_epi16(temp0, temp1);//s1+s4 s2+s3 a1+a4 a2+a3 0 0 0 0 temp0 = _mm_unpacklo_epi32(temp0, temp2);//s1+s4 s2+s3 (s1-s3<<1) (s4-s2<<1) a1+a4 a2+a3 (a1-a3<<1) (a4-a2<<1) temp1 = _mm_unpacklo_epi32(temp4, temp3);//s1+s2 s4+s3 (s2-s4<<1) (s3-s1<<1) a1+a2 a4+a3 (a2-a4<<1) (a3-a1<<1) temp2 = _mm_unpacklo_epi64(temp0, temp1);//s1+s4 s2+s3 (s1-s3<<1) (s4-s2<<1) s1+s2 s4+s3 (s2-s4<<1) (s3-s1<<1) temp3 = _mm_unpackhi_epi64(temp0, temp1); //a1+a4 a2+a3 (a1-a3<<1) (a4-a2<<1) a1+a2 a4+a3 (s2-s4<<1) (s3-s1<<1) sad_b1 = _mm_sub_epi16(sad_b1, temp2); //lsi values Block0 sad_b2 = _mm_sub_epi16(sad_b2, temp3); //lsi values Block1 temp0 = _mm_cmpgt_epi16(threshold, sad_b1); //if any threshold[i]>ls[i], corresponding 16-bit value in temp becomes 0xffff temp1 = _mm_cmpgt_epi16(threshold, sad_b2); temp0 = _mm_xor_si128(temp0, all_one); //Xor with 1 => NOT operation temp1 = _mm_xor_si128(temp1, all_one); test1 = _mm_test_all_zeros(temp0, all_one); test2 = _mm_test_all_zeros(temp1, all_one); if (test1 == 0 || test2 == 0 || pu2_thrsh[8] <= sad_1 || pu2_thrsh[8] <= sad_2) flag = 1; } pu1_src += 8; pu1_est += 8; src_r0 = _mm_loadl_epi64((__m128i *) pu1_src); //Row 0 - Block1 and 2 src_r1 = _mm_loadl_epi64((__m128i *) (pu1_src + src_strd)); //Row 1 - Block1 and 2 src_r2 = _mm_loadl_epi64((__m128i *) (pu1_src + 2 * src_strd)); //Row 2 - Block1 and 2 src_r3 = _mm_loadl_epi64((__m128i *) (pu1_src + 3 * src_strd)); //Row 3 - Block1 and 2 src_r0 = _mm_cvtepu8_epi16(src_r0); src_r1 = _mm_cvtepu8_epi16(src_r1); src_r2 = _mm_cvtepu8_epi16(src_r2); src_r3 = _mm_cvtepu8_epi16(src_r3); est_r0 = _mm_loadl_epi64((__m128i *) pu1_est); est_r1 = _mm_loadl_epi64((__m128i *) (pu1_est + est_strd)); est_r2 = _mm_loadl_epi64((__m128i *) (pu1_est + 2 * est_strd)); est_r3 = _mm_loadl_epi64((__m128i *) (pu1_est + 3 * est_strd)); est_r0 = _mm_cvtepu8_epi16(est_r0); est_r1 = _mm_cvtepu8_epi16(est_r1); est_r2 = _mm_cvtepu8_epi16(est_r2); est_r3 = _mm_cvtepu8_epi16(est_r3); src_r0 = _mm_sub_epi16(src_r0, est_r0); src_r1 = _mm_sub_epi16(src_r1, est_r1); src_r2 = _mm_sub_epi16(src_r2, est_r2); src_r3 = _mm_sub_epi16(src_r3, est_r3); src_r0 = _mm_abs_epi16(src_r0); src_r1 = _mm_abs_epi16(src_r1); src_r2 = _mm_abs_epi16(src_r2); src_r3 = _mm_abs_epi16(src_r3); src_r0 = _mm_add_epi16(src_r0, src_r3); //s1 s4 s4 s1 a1 a4 a4 a1 src_r1 = _mm_add_epi16(src_r1, src_r2); //s2 s3 s3 s2 a2 a3 a3 a2 //SAD calculation temp0 = _mm_add_epi16(src_r0, src_r1); temp0 = _mm_hadd_epi16(temp0, zero); temp0 = _mm_hadd_epi16(temp0, zero); //sad1, sad2 - 16bit values sad_1 = _mm_extract_epi16(temp0, 0); sad_2 = _mm_extract_epi16(temp0, 1); (*pi4_mb_distortion) += sad_1 + sad_2; if (flag == 0) { sad_b1 = _mm_set1_epi16((sad_1 << 1)); sad_b2 = _mm_set1_epi16((sad_2 << 1)); src_r0 = _mm_shufflelo_epi16(src_r0, 0x9c); //Block 0 s1 s1 s4 s4 a1 a4 a4 a1 src_r0 = _mm_shufflehi_epi16(src_r0, 0x9c); //Block 1 s1 s1 s4 s4 a1 a1 a4 a4 src_r1 = _mm_shufflelo_epi16(src_r1, 0x9c); //Block 0 s2 s2 s3 s3 a2 a3 a3 a2 src_r1 = _mm_shufflehi_epi16(src_r1, 0x9c); //Block 1 s2 s2 s3 s3 a2 a2 a3 a3 src_r0 = _mm_hadd_epi16(src_r0, zero); //s1 s4 a1 a4 0 0 0 0 src_r1 = _mm_hadd_epi16(src_r1, zero); //s2 s3 a2 a3 0 0 0 0 temp0 = _mm_slli_epi16(src_r0, 1);//s1<<1 s4<<1 a1<<1 a4<<1 0 0 0 0 temp1 = _mm_slli_epi16(src_r1, 1);//s2<<1 s3<<1 a2<<1 a3<<1 0 0 0 0 temp0 = _mm_shufflelo_epi16(temp0, 0xb1);//s4<<1 s1<<1 a4<<1 a1<<1 0 0 0 0 temp1 = _mm_shufflelo_epi16(temp1, 0xb1);//s3<<1 s2<<1 a3<<1 a2<<1 0 0 0 0 temp2 = _mm_sub_epi16(src_r0, temp1);//(s1-s3<<1) (s4-s2<<1) (a1-a3<<1) (a4-a2<<1) 0 0 0 0 temp3 = _mm_sub_epi16(src_r1, temp0);//(s2-s4<<1) (s3-s1<<1) (a2-a4<<1) (a3-a1<<1) 0 0 0 0 temp4 = _mm_add_epi16(src_r0, src_r1);//s1+s2 s4+s3 a1+a2 a4+a3 0 0 0 0 temp0 = _mm_hadd_epi16(src_r0, zero); //s1+s4 a1+a4 0 0 0 0 0 0 temp1 = _mm_hadd_epi16(src_r1, zero); //s2+s3 a2+a3 0 0 0 0 0 0 temp0 = _mm_unpacklo_epi16(temp0, temp1);//s1+s4 s2+s3 a1+a4 a2+a3 0 0 0 0 temp0 = _mm_unpacklo_epi32(temp0, temp2);//s1+s4 s2+s3 (s1-s3<<1) (s4-s2<<1) a1+a4 a2+a3 (a1-a3<<1) (a4-a2<<1) temp1 = _mm_unpacklo_epi32(temp4, temp3);//s1+s2 s4+s3 (s2-s4<<1) (s3-s1<<1) a1+a2 a4+a3 (a2-a4<<1) (a3-a1<<1) temp2 = _mm_unpacklo_epi64(temp0, temp1);//s1+s4 s2+s3 (s1-s3<<1) (s4-s2<<1) s1+s2 s4+s3 (s2-s4<<1) (s3-s1<<1) temp3 = _mm_unpackhi_epi64(temp0, temp1); //a1+a4 a2+a3 (a1-a3<<1) (a4-a2<<1) a1+a2 a4+a3 (s2-s4<<1) (s3-s1<<1) sad_b1 = _mm_sub_epi16(sad_b1, temp2); //lsi values Block0 sad_b2 = _mm_sub_epi16(sad_b2, temp3); //lsi values Block1 temp0 = _mm_cmpgt_epi16(threshold, sad_b1); //if any threshold[i]>ls[i], corresponding 16-bit value in temp becomes 0xffff temp1 = _mm_cmpgt_epi16(threshold, sad_b2); temp0 = _mm_xor_si128(temp0, all_one); //Xor with 1 => NOT operation temp1 = _mm_xor_si128(temp1, all_one); test1 = _mm_test_all_zeros(temp0, all_one); test2 = _mm_test_all_zeros(temp1, all_one); if (test1 == 0 || test2 == 0 || pu2_thrsh[8] <= sad_1 || pu2_thrsh[8] <= sad_2) flag = 1; } pu1_src += 4*src_strd - 8; pu1_est += 4*est_strd - 8; } *pu4_is_zero = flag; }