blob: 34ea090fda0a4523c4cbed48b36c1ee342d2d098 [file] [log] [blame]
/******************************************************************************
*
* Copyright (C) 2012 Ittiam Systems Pvt Ltd, Bangalore
*
* 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.
*
******************************************************************************/
/**
*******************************************************************************
* @file
* ihevc_deblck_atom_intr.c
*
* @brief
* Contains function definitions for deblocking filters
*
* @author
* Rishab
*
* @par List of Functions:
* - ihevc_deblk_luma_vert_ssse3()
* - ihevc_deblk_luma_horz_ssse3()
* - ihevc_deblk_chroma_vert_ssse3()
* - ihevc_deblk_chroma_horz_ssse3()
*
* @remarks
* None
*
*******************************************************************************
*/
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include "ihevc_typedefs.h"
#include "ihevc_platform_macros.h"
#include "ihevc_macros.h"
#include "ihevc_deblk.h"
#include "ihevc_deblk_tables.h"
#include "ihevc_debug.h"
#include "ihevc_tables_x86_intr.h"
#include <immintrin.h>
/**
*******************************************************************************
*
* @brief
* Decision process and filtering for the luma block vertical edge.
*
* @par Description:
* The decision process for the luma block vertical edge is carried out and
* an appropriate filter is applied. The boundary filter strength, bs should
* be greater than 0. The pcm flags and the transquant bypass flags should
* be taken care of by the calling function.
*
* @param[in] pu1_src
* Pointer to the src sample q(0,0)
*
* @param[in] src_strd
* Source stride
*
* @param[in] bs
* Boundary filter strength of q(0,0)
*
* @param[in] quant_param_p
* quantization parameter of p block
*
* @param[in] quant_param_q
* quantization parameter of p block
*
* @param[in] beta_offset_div2
*
*
* @param[in] tc_offset_div2
*
*
* @param[in] filter_flag_p
* flag whether to filter the p block
*
* @param[in] filter_flag_q
* flag whether to filter the q block
*
* @returns
*
* @remarks
* None
*
*******************************************************************************
*/
void ihevc_deblk_luma_vert_ssse3(UWORD8 *pu1_src,
WORD32 src_strd,
WORD32 bs,
WORD32 quant_param_p,
WORD32 quant_param_q,
WORD32 beta_offset_div2,
WORD32 tc_offset_div2,
WORD32 filter_flag_p,
WORD32 filter_flag_q)
{
WORD32 qp_luma, beta_indx, tc_indx;
WORD32 beta, tc;
WORD32 d, dp, dq, d_sam0, d_sam3;
WORD32 d3, d0, de_0, de_1, de_2, de_3;
WORD32 de, dep, deq;
__m128i src_row0_8x16b, src_row1_8x16b, src_row2_8x16b, src_row3_8x16b;
{
__m128i src_tmp_8x16b, coef_8x16b, mask_d_result_4x32b, mask_de_result_8x16b;
__m128i mask_16x8b, temp_coef0_8x16b, temp_coef1_8x16b;
ASSERT((bs > 0) && (bs <= 3));
ASSERT(filter_flag_p || filter_flag_q);
qp_luma = (quant_param_p + quant_param_q + 1) >> 1;
beta_indx = CLIP3(qp_luma + (beta_offset_div2 << 1), 0, 51);
/* BS based on implementation can take value 3 if it is intra/inter egde */
/* based on BS, tc index is calcuated by adding 2 * ( bs - 1) to QP and tc_offset */
/* for BS = 1 adding factor is (0*2), BS = 2 or 3 adding factor is (1*2) */
/* the above desired functionallity is achieved by doing (2*(bs>>1)) */
tc_indx = CLIP3(qp_luma + (2 * (bs >> 1)) + (tc_offset_div2 << 1), 0, 53);
beta = gai4_ihevc_beta_table[beta_indx];
tc = gai4_ihevc_tc_table[tc_indx];
if(0 == tc)
{
return;
}
src_row0_8x16b = _mm_loadl_epi64((__m128i *)(pu1_src - 4));
src_row3_8x16b = _mm_loadl_epi64((__m128i *)((pu1_src - 4) + 3 * src_strd));
coef_8x16b = _mm_load_si128((__m128i *)(coef_d));
mask_16x8b = _mm_load_si128((__m128i *)(shuffle_d));
src_tmp_8x16b = _mm_unpacklo_epi64(src_row0_8x16b, src_row3_8x16b);
mask_de_result_8x16b = _mm_shuffle_epi8(src_tmp_8x16b, mask_16x8b);
mask_d_result_4x32b = _mm_maddubs_epi16(src_tmp_8x16b, coef_8x16b);
//to get all 1's of 8 bit in (1)
temp_coef0_8x16b = _mm_cmpeq_epi16(src_tmp_8x16b, src_tmp_8x16b);
temp_coef1_8x16b = _mm_srli_epi16(temp_coef0_8x16b, 15);
//accumulating values foe dp3 dq3 , dp0 dq0 values
mask_d_result_4x32b = _mm_madd_epi16(mask_d_result_4x32b, temp_coef1_8x16b);
temp_coef1_8x16b = _mm_packus_epi16(temp_coef1_8x16b, temp_coef1_8x16b);
// to get all 1,-1 sets of 16 bits in (0)
temp_coef0_8x16b = _mm_unpacklo_epi8(temp_coef0_8x16b, temp_coef1_8x16b);
//q33-q30,p33-p30,q03-q00,p03-p00,0,q30-p30,0,q00-p00
mask_de_result_8x16b = _mm_maddubs_epi16(mask_de_result_8x16b, temp_coef0_8x16b);
//to get 16 bit 1's
temp_coef0_8x16b = _mm_srli_epi16(temp_coef1_8x16b, 8);
// dq3 dp3 dq0 dp0
mask_d_result_4x32b = _mm_abs_epi32(mask_d_result_4x32b);
mask_16x8b = _mm_shuffle_epi32(mask_d_result_4x32b, 0xec);
mask_d_result_4x32b = _mm_shuffle_epi32(mask_d_result_4x32b, 0x49);
// dq dp d3 d0
mask_d_result_4x32b = _mm_add_epi32(mask_d_result_4x32b, mask_16x8b);
//|q33-q30|,|p33-p30|,|q03-q00|,|p03-p00|,0,|q30-p30|,0,|q00-p00|
mask_de_result_8x16b = _mm_abs_epi16(mask_de_result_8x16b);
//|q33-q30|+|p33-p30|,|q03-q00|+|p03-p00|,0+|q30-p30|,0+|q00-p00|
mask_de_result_8x16b = _mm_madd_epi16(mask_de_result_8x16b, temp_coef0_8x16b);
///store back in a single variable
temp_coef0_8x16b = _mm_srli_si128(mask_d_result_4x32b, 4);
temp_coef1_8x16b = _mm_srli_si128(mask_d_result_4x32b, 8);
mask_16x8b = _mm_srli_si128(mask_d_result_4x32b, 12);
d0 = _mm_cvtsi128_si32(mask_d_result_4x32b);
d3 = _mm_cvtsi128_si32(temp_coef0_8x16b);
dp = _mm_cvtsi128_si32(temp_coef1_8x16b);
dq = _mm_cvtsi128_si32(mask_16x8b);
//getting d
d = d0 + d3;
///store back in a single variable
temp_coef0_8x16b = _mm_srli_si128(mask_de_result_8x16b, 4);
temp_coef1_8x16b = _mm_srli_si128(mask_de_result_8x16b, 8);
mask_16x8b = _mm_srli_si128(mask_de_result_8x16b, 12);
de_0 = _mm_cvtsi128_si32(mask_de_result_8x16b);
de_1 = _mm_cvtsi128_si32(temp_coef0_8x16b);
de_2 = _mm_cvtsi128_si32(temp_coef1_8x16b);
de_3 = _mm_cvtsi128_si32(mask_16x8b);
de = 0;
dep = 0;
deq = 0;
if(d < beta)
{
d_sam0 = 0;
if((2 * d0 < (beta >> 2))
&& (de_2 < (beta >> 3))
&& (de_0 < ((5 * tc + 1) >> 1)))
{
d_sam0 = 1;
}
d_sam3 = 0;
if((2 * d3 < (beta >> 2))
&& (de_3 < (beta >> 3))
&& de_1 < ((5 * tc + 1) >> 1))
{
d_sam3 = 1;
}
de = (d_sam0 & d_sam3) + 1;
dep = (dp < (beta + (beta >> 1)) >> 3) ? 1 : 0;
deq = (dq < (beta + (beta >> 1)) >> 3) ? 1 : 0;
if(tc <= 1)
{
dep = 0;
deq = 0;
}
}
}
if(de != 0)
{
src_row1_8x16b = _mm_loadl_epi64((__m128i *)((pu1_src - 4) + src_strd));
src_row2_8x16b = _mm_loadl_epi64((__m128i *)((pu1_src - 4) + 2 * src_strd));
if(de == 2)
{
__m128i temp_pq_str0_16x8b;
__m128i temp_pq1_str0_16x8b, temp_pq1_str1_16x8b;
__m128i temp_pq2_str0_16x8b;
__m128i temp_pq_str1_16x8b;
__m128i temp_str0_16x8b, temp_str1_16x8b, temp_str2_16x8b, temp_str3_16x8b;
__m128i temp_max0_16x8b, temp_max1_16x8b, temp_min0_16x8b, temp_min1_16x8b;
__m128i const2_8x16b, const2tc_8x16b;
LWORD64 mask, tc2;
tc = tc << 1;
mask = (((LWORD64)filter_flag_q) << 63) | (((LWORD64)filter_flag_p) << 31);
tc2 = ((LWORD64)tc);
const2_8x16b = _mm_cmpeq_epi16(src_row0_8x16b, src_row0_8x16b);
//q'0-q'1-2 ,p'0-p'1-2
src_row0_8x16b = _mm_unpacklo_epi64(src_row0_8x16b, src_row2_8x16b);
src_row1_8x16b = _mm_unpacklo_epi64(src_row1_8x16b, src_row3_8x16b);
const2_8x16b = _mm_srli_epi16(const2_8x16b, 15);
temp_pq_str0_16x8b = _mm_srli_epi64(src_row0_8x16b, 16);
temp_pq_str1_16x8b = _mm_srli_epi64(src_row1_8x16b, 16);
//arranged x x x x x x x x q31 q30 q1 q10 p30 p31 p10 p11 , x x x x x x x x q21 q20 q01 q00 p20 p21 p00 p01
temp_str0_16x8b = _mm_unpacklo_epi16(temp_pq_str0_16x8b, temp_pq_str1_16x8b);
temp_str1_16x8b = _mm_unpackhi_epi16(temp_pq_str0_16x8b, temp_pq_str1_16x8b);
const2_8x16b = _mm_packus_epi16(const2_8x16b, const2_8x16b);
//arranged q31 q30 q21 q20 q1 q10 q01 q00 p30 p31 p20 p21 p10 p11 p00 p01
temp_pq_str0_16x8b = _mm_unpacklo_epi32(temp_str0_16x8b, temp_str1_16x8b);
temp_pq_str0_16x8b = _mm_maddubs_epi16(temp_pq_str0_16x8b, const2_8x16b);
//q'1-2, p'1-2
temp_pq1_str0_16x8b = _mm_srli_epi64(src_row0_8x16b, 8);
temp_pq1_str1_16x8b = _mm_srli_epi64(src_row1_8x16b, 8);
temp_str2_16x8b = _mm_unpacklo_epi16(temp_pq1_str0_16x8b, temp_pq1_str1_16x8b);
temp_str3_16x8b = _mm_unpackhi_epi16(temp_pq1_str0_16x8b, temp_pq1_str1_16x8b);
temp_str2_16x8b = _mm_shuffle_epi32(temp_str2_16x8b, 0x58);
temp_str3_16x8b = _mm_shuffle_epi32(temp_str3_16x8b, 0x58);
// q30 p30 q20 p20 q10 p10 q01 q00 p30 q20 p20 q10 p10 q01 q00 p00
temp_pq1_str0_16x8b = _mm_unpackhi_epi32(temp_str2_16x8b, temp_str3_16x8b);
// q32 q31 q22 q21 q12 q11 q02 q01 p32 p31 p22 p21 p12 p11 p02 p01
temp_pq1_str1_16x8b = _mm_unpacklo_epi32(temp_str2_16x8b, temp_str3_16x8b);
temp_pq1_str0_16x8b = _mm_maddubs_epi16(temp_pq1_str0_16x8b, const2_8x16b);
temp_pq1_str1_16x8b = _mm_maddubs_epi16(temp_pq1_str1_16x8b, const2_8x16b);
//clipping mask design
temp_str1_16x8b = _mm_setzero_si128();
temp_str0_16x8b = _mm_loadl_epi64((__m128i *)(&mask));
const2tc_8x16b = _mm_loadl_epi64((__m128i *)(&tc2));
temp_str0_16x8b = _mm_shuffle_epi32(temp_str0_16x8b, 0x44);
const2tc_8x16b = _mm_shuffle_epi8(const2tc_8x16b, temp_str1_16x8b);
//clipping mask design
temp_str0_16x8b = _mm_srai_epi32(temp_str0_16x8b, 31);
const2tc_8x16b = _mm_and_si128(const2tc_8x16b, temp_str0_16x8b);
//calculating Clipping MAX for all pixel values.
temp_max0_16x8b = _mm_adds_epu8(src_row0_8x16b, const2tc_8x16b);
temp_max1_16x8b = _mm_adds_epu8(src_row1_8x16b, const2tc_8x16b);
//q'2-q'0-2,p'2-p'0-2
temp_pq2_str0_16x8b = _mm_unpacklo_epi16(src_row0_8x16b, src_row2_8x16b);
temp_str3_16x8b = _mm_unpacklo_epi16(src_row1_8x16b, src_row3_8x16b);
temp_pq2_str0_16x8b = _mm_shuffle_epi32(temp_pq2_str0_16x8b, 0x5c);
temp_str3_16x8b = _mm_shuffle_epi32(temp_str3_16x8b, 0x5c);
const2_8x16b = _mm_slli_epi16(const2_8x16b, 1);
//arranged q33 q32 q23 q22 q13 q12 q03 q02 p33 p32 p23 p22 p13 p12 p03 p02
temp_str3_16x8b = _mm_unpacklo_epi16(temp_pq2_str0_16x8b, temp_str3_16x8b);
temp_pq2_str0_16x8b = _mm_maddubs_epi16(temp_str3_16x8b, const2_8x16b);
//calculating Clipping MIN for all pixel values.
temp_min0_16x8b = _mm_subs_epu8(src_row0_8x16b, const2tc_8x16b);
temp_min1_16x8b = _mm_subs_epu8(src_row1_8x16b, const2tc_8x16b);
//q'0-q'1-2 ,p'0-p'1-2
temp_pq_str1_16x8b = _mm_shuffle_epi32(temp_pq_str0_16x8b, 0x4e);
temp_pq_str0_16x8b = _mm_add_epi16(temp_pq_str0_16x8b, temp_pq_str1_16x8b);
//q'1-2 p'1-2
temp_pq1_str0_16x8b = _mm_add_epi16(temp_pq1_str0_16x8b, temp_pq1_str1_16x8b);
//to get 2 in 16 bit
const2_8x16b = _mm_srli_epi16(const2_8x16b, 8);
//to get q33 q23 q13 q03, p33 p23 p13 p03
temp_pq1_str1_16x8b = _mm_slli_epi16(temp_str3_16x8b, 8);
temp_pq_str1_16x8b = _mm_srli_epi16(temp_str3_16x8b, 8);
temp_pq1_str1_16x8b = _mm_srli_epi16(temp_pq1_str1_16x8b, 8);
//q'1, p'1 (adding 2)
temp_pq1_str0_16x8b = _mm_add_epi16(temp_pq1_str0_16x8b, const2_8x16b);
//q'0-q'1,p'0-p'1
temp_pq_str0_16x8b = _mm_add_epi16(temp_pq_str0_16x8b, const2_8x16b);
//q'2-q'1,p'2-p'1
temp_pq2_str0_16x8b = _mm_add_epi16(temp_pq2_str0_16x8b, const2_8x16b);
//q'0 = (q'0-q'1)+q'1 ,p'0 = (p'0-p'1)+p'1;
temp_pq_str0_16x8b = _mm_add_epi16(temp_pq1_str0_16x8b, temp_pq_str0_16x8b);
//q'2 = (q'2-q'1)+q'1 ,p'2 = (p'2-p'1)+p'1;
temp_pq2_str0_16x8b = _mm_add_epi16(temp_pq1_str0_16x8b, temp_pq2_str0_16x8b);
//normalisation of all modified pixels
temp_pq_str0_16x8b = _mm_srai_epi16(temp_pq_str0_16x8b, 3);
temp_pq1_str0_16x8b = _mm_srai_epi16(temp_pq1_str0_16x8b, 2);
temp_pq2_str0_16x8b = _mm_srai_epi16(temp_pq2_str0_16x8b, 3);
//getting p0 p1 together and p2 p3 together
temp_str0_16x8b = _mm_unpacklo_epi16(temp_pq1_str0_16x8b, temp_pq_str0_16x8b);
temp_str2_16x8b = _mm_unpacklo_epi16(temp_pq1_str1_16x8b, temp_pq2_str0_16x8b);
//getting q1 q0 together and q3 q2 together
temp_pq_str0_16x8b = _mm_unpackhi_epi16(temp_pq_str0_16x8b, temp_pq1_str0_16x8b);
temp_pq2_str0_16x8b = _mm_unpackhi_epi16(temp_pq2_str0_16x8b, temp_pq_str1_16x8b);
//getting p's of row0 row1 together and of row2 row3 together
temp_pq_str1_16x8b = _mm_unpacklo_epi32(temp_str2_16x8b, temp_str0_16x8b);
temp_str2_16x8b = _mm_unpackhi_epi32(temp_str2_16x8b, temp_str0_16x8b);
//getting q's of row0 row1 together and of row2 row3 together
temp_str0_16x8b = _mm_unpacklo_epi32(temp_pq_str0_16x8b, temp_pq2_str0_16x8b);
temp_pq_str0_16x8b = _mm_unpackhi_epi32(temp_pq_str0_16x8b, temp_pq2_str0_16x8b);
//getting values for respective rows in 16 bit
src_row0_8x16b = _mm_unpacklo_epi64(temp_pq_str1_16x8b, temp_str0_16x8b);
src_row1_8x16b = _mm_unpackhi_epi64(temp_pq_str1_16x8b, temp_str0_16x8b);
src_row2_8x16b = _mm_unpacklo_epi64(temp_str2_16x8b, temp_pq_str0_16x8b);
src_row3_8x16b = _mm_unpackhi_epi64(temp_str2_16x8b, temp_pq_str0_16x8b);
//packing values to 8 bit
src_row0_8x16b = _mm_packus_epi16(src_row0_8x16b, src_row2_8x16b);
src_row1_8x16b = _mm_packus_epi16(src_row1_8x16b, src_row3_8x16b);
//Clipping MAX
src_row0_8x16b = _mm_min_epu8(src_row0_8x16b, temp_max0_16x8b);
src_row1_8x16b = _mm_min_epu8(src_row1_8x16b, temp_max1_16x8b);
//Clipping MIN
src_row0_8x16b = _mm_max_epu8(src_row0_8x16b, temp_min0_16x8b);
src_row1_8x16b = _mm_max_epu8(src_row1_8x16b, temp_min1_16x8b);
//separating row 2 and row 3
src_row2_8x16b = _mm_srli_si128(src_row0_8x16b, 8);
src_row3_8x16b = _mm_srli_si128(src_row1_8x16b, 8);
}
else
{
__m128i tmp_delta0_8x16b, tmp_delta1_8x16b, tmp_delta2_8x16b, tmp_delta3_8x16b;
__m128i tmp0_const_8x16b, tmp1_const_8x16b, tmp2_const_8x16b, tmp3_const_8x16b;
__m128i coefdelta_0_8x16b, mask_pq_8x16b;
__m128i const2_8x16b, consttc_8x16b;
LWORD64 mask1;
mask1 = (((LWORD64)(filter_flag_q & deq)) << 63) | (((LWORD64)filter_flag_q) << 47) | (((LWORD64)filter_flag_p) << 31) | (((LWORD64)(filter_flag_p & dep)) << 15);
consttc_8x16b = _mm_set1_epi32(tc);
src_row0_8x16b = _mm_unpacklo_epi64(src_row0_8x16b, src_row1_8x16b);
src_row2_8x16b = _mm_unpacklo_epi64(src_row2_8x16b, src_row3_8x16b);
tmp_delta2_8x16b = _mm_srli_epi64(src_row0_8x16b, 16);
tmp_delta3_8x16b = _mm_srli_epi64(src_row2_8x16b, 16);
tmp_delta2_8x16b = _mm_shuffle_epi32(tmp_delta2_8x16b, 0x08);
tmp_delta3_8x16b = _mm_shuffle_epi32(tmp_delta3_8x16b, 0x08);
//arranged q31 q30 p30 p31 q21 q20 p20 p21 q1 q10 p10 p11 q01 q00 p00 p01
tmp_delta2_8x16b = _mm_unpacklo_epi64(tmp_delta2_8x16b, tmp_delta3_8x16b);
coefdelta_0_8x16b = _mm_load_si128((__m128i *)coef_de1);
// (-3q1+9q0),(-9p0+3p1)
tmp_delta3_8x16b = _mm_maddubs_epi16(tmp_delta2_8x16b, coefdelta_0_8x16b);
//converting to 16 bit
consttc_8x16b = _mm_packs_epi32(consttc_8x16b, consttc_8x16b);
//getting -tc store
tmp1_const_8x16b = _mm_cmpeq_epi32(consttc_8x16b, consttc_8x16b);
//calc 10 *tc = 2*tc +8*tc ; 2*tc
tmp2_const_8x16b = _mm_slli_epi16(consttc_8x16b, 1);
//calc 10 *tc = 2*tc +8*tc ; 8*tc
tmp0_const_8x16b = _mm_slli_epi16(consttc_8x16b, 3);
//getting -tc store
tmp3_const_8x16b = _mm_sign_epi16(consttc_8x16b, tmp1_const_8x16b);
//calc 10 *tc
tmp2_const_8x16b = _mm_add_epi16(tmp2_const_8x16b, tmp0_const_8x16b);
//const 1
const2_8x16b = _mm_srli_epi16(tmp1_const_8x16b, 15);
tmp_delta0_8x16b = _mm_madd_epi16(tmp_delta3_8x16b, const2_8x16b);
const2_8x16b = _mm_srli_epi32(tmp1_const_8x16b, 31);
//getting the mask values
mask_pq_8x16b = _mm_loadl_epi64((__m128i *)(&mask1));
//loaded coef for delta1 calculation
coefdelta_0_8x16b = _mm_load_si128((__m128i *)coef_dep1);
//(-2q1+q0),(p0-2p1)
tmp_delta3_8x16b = _mm_maddubs_epi16(tmp_delta2_8x16b, coefdelta_0_8x16b);
//const 8
const2_8x16b = _mm_slli_epi32(const2_8x16b, 3);
//rearranging the mask values
mask_pq_8x16b = _mm_unpacklo_epi64(mask_pq_8x16b, mask_pq_8x16b);
//normalisation of the filter
tmp_delta0_8x16b = _mm_add_epi32(tmp_delta0_8x16b, const2_8x16b);
tmp_delta0_8x16b = _mm_srai_epi32(tmp_delta0_8x16b, 4);
//getting deltaq0
tmp_delta2_8x16b = _mm_sign_epi32(tmp_delta0_8x16b, tmp1_const_8x16b);
//packing d3q d2q d1q d0q d3p d2p d1p d0p
tmp_delta0_8x16b = _mm_packs_epi32(tmp_delta0_8x16b, tmp_delta2_8x16b);
//absolute delta
tmp_delta2_8x16b = _mm_abs_epi16(tmp_delta0_8x16b);
//Clipping of delta0
tmp_delta0_8x16b = _mm_min_epi16(tmp_delta0_8x16b, consttc_8x16b);
//mask for |delta| < 10*tc
tmp0_const_8x16b = _mm_cmpgt_epi16(tmp2_const_8x16b, tmp_delta2_8x16b);
//Clipping of delta0
tmp_delta0_8x16b = _mm_max_epi16(tmp_delta0_8x16b, tmp3_const_8x16b);
//delta 1 calc starts
//getting q32 q22 q12 q02 p32 p12 p22 p02
tmp2_const_8x16b = _mm_loadl_epi64((__m128i *)(shuffle0));
tmp_delta2_8x16b = _mm_shuffle_epi8(src_row0_8x16b, tmp2_const_8x16b);
tmp_delta1_8x16b = _mm_shuffle_epi8(src_row2_8x16b, tmp2_const_8x16b);
tmp_delta1_8x16b = _mm_unpacklo_epi32(tmp_delta2_8x16b, tmp_delta1_8x16b);
//constant 1
const2_8x16b = _mm_srli_epi16(tmp1_const_8x16b, 15);
//tc>>1 16 bit
consttc_8x16b = _mm_srai_epi16(consttc_8x16b, 1);
//getting -tc>>1 store 16 bit
tmp1_const_8x16b = _mm_sign_epi16(consttc_8x16b, tmp1_const_8x16b);
//2*delta0
tmp2_const_8x16b = _mm_add_epi16(tmp_delta0_8x16b, tmp_delta0_8x16b);
//getting all respective q's and p's together
tmp3_const_8x16b = _mm_load_si128((__m128i *)(shuffle1));
tmp_delta3_8x16b = _mm_shuffle_epi8(tmp_delta3_8x16b, tmp3_const_8x16b);
//final adds for deltap1 and deltaq1
tmp_delta3_8x16b = _mm_add_epi16(tmp_delta3_8x16b, const2_8x16b);
tmp_delta1_8x16b = _mm_add_epi16(tmp_delta1_8x16b, tmp2_const_8x16b);
tmp_delta1_8x16b = _mm_add_epi16(tmp_delta1_8x16b, tmp_delta3_8x16b);
tmp2_const_8x16b = _mm_setzero_si128();
tmp_delta1_8x16b = _mm_srai_epi16(tmp_delta1_8x16b, 2);
// clipping delta1
tmp_delta1_8x16b = _mm_min_epi16(tmp_delta1_8x16b, consttc_8x16b);
// clipping delta1
tmp_delta1_8x16b = _mm_max_epi16(tmp_delta1_8x16b, tmp1_const_8x16b);
//getting the mask ready
mask_pq_8x16b = _mm_srai_epi16(mask_pq_8x16b, 15);
//masking of the delta values |delta|<10*tc
tmp_delta1_8x16b = _mm_and_si128(tmp_delta1_8x16b, tmp0_const_8x16b);
tmp_delta0_8x16b = _mm_and_si128(tmp_delta0_8x16b, tmp0_const_8x16b);
//packing dq1 dq0 dp0 dp1
tmp1_const_8x16b = _mm_unpacklo_epi16(tmp_delta1_8x16b, tmp_delta0_8x16b);
tmp_delta0_8x16b = _mm_unpackhi_epi16(tmp_delta0_8x16b, tmp_delta1_8x16b);
tmp_delta1_8x16b = _mm_unpackhi_epi32(tmp1_const_8x16b, tmp_delta0_8x16b);
tmp_delta0_8x16b = _mm_unpacklo_epi32(tmp1_const_8x16b, tmp_delta0_8x16b);
//masking of the delta values dep, deq , filter_p ,filter_q
tmp_delta0_8x16b = _mm_and_si128(tmp_delta0_8x16b, mask_pq_8x16b);
tmp_delta1_8x16b = _mm_and_si128(tmp_delta1_8x16b, mask_pq_8x16b);
//converting 8bit to 16 bit
src_row0_8x16b = _mm_unpacklo_epi8(src_row0_8x16b, tmp2_const_8x16b);
src_row1_8x16b = _mm_unpacklo_epi8(src_row1_8x16b, tmp2_const_8x16b);
src_row2_8x16b = _mm_unpacklo_epi8(src_row2_8x16b, tmp2_const_8x16b);
src_row3_8x16b = _mm_unpacklo_epi8(src_row3_8x16b, tmp2_const_8x16b);
//shuffle values loaded
tmp0_const_8x16b = _mm_load_si128((__m128i *)shuffle2);
tmp1_const_8x16b = _mm_load_si128((__m128i *)shuffle3);
//arranging each row delta in different registers
tmp_delta3_8x16b = _mm_shuffle_epi8(tmp_delta1_8x16b, tmp1_const_8x16b);
tmp_delta2_8x16b = _mm_shuffle_epi8(tmp_delta1_8x16b, tmp0_const_8x16b);
tmp_delta1_8x16b = _mm_shuffle_epi8(tmp_delta0_8x16b, tmp1_const_8x16b);
tmp_delta0_8x16b = _mm_shuffle_epi8(tmp_delta0_8x16b, tmp0_const_8x16b);
//adding the respective delta
src_row3_8x16b = _mm_add_epi16(tmp_delta3_8x16b, src_row3_8x16b);
src_row2_8x16b = _mm_add_epi16(tmp_delta2_8x16b, src_row2_8x16b);
src_row1_8x16b = _mm_add_epi16(tmp_delta1_8x16b, src_row1_8x16b);
src_row0_8x16b = _mm_add_epi16(tmp_delta0_8x16b, src_row0_8x16b);
//saturating to 8 bit
src_row2_8x16b = _mm_packus_epi16(src_row2_8x16b, src_row3_8x16b);
src_row0_8x16b = _mm_packus_epi16(src_row0_8x16b, src_row1_8x16b);
//separating different rows
src_row1_8x16b = _mm_srli_si128(src_row0_8x16b, 8);
src_row3_8x16b = _mm_srli_si128(src_row2_8x16b, 8);
}
_mm_storel_epi64((__m128i *)(pu1_src - 4), src_row0_8x16b);
_mm_storel_epi64((__m128i *)((pu1_src - 4) + src_strd), src_row1_8x16b);
_mm_storel_epi64((__m128i *)((pu1_src - 4) + 2 * src_strd), src_row2_8x16b);
_mm_storel_epi64((__m128i *)((pu1_src - 4) + 3 * src_strd), src_row3_8x16b);
}
}
void ihevc_deblk_luma_horz_ssse3(UWORD8 *pu1_src,
WORD32 src_strd,
WORD32 bs,
WORD32 quant_param_p,
WORD32 quant_param_q,
WORD32 beta_offset_div2,
WORD32 tc_offset_div2,
WORD32 filter_flag_p,
WORD32 filter_flag_q)
{
WORD32 qp_luma, beta_indx, tc_indx;
WORD32 beta, tc;
WORD32 d0, d3, dp, dq, d;
WORD32 de_0, de_1, de_2, de_3;
WORD32 d_sam0, d_sam3;
WORD32 de, dep, deq;
__m128i src_q0_8x16b, src_q1_8x16b, src_p0_8x16b, src_p1_8x16b, src_q2_8x16b;
__m128i tmp_pq_str1_8x16b, src_p2_8x16b, tmp_pq_str0_8x16b;
{
__m128i src_tmp_p_0_8x16b, src_tmp_p_1_8x16b, src_tmp_q_0_8x16b, src_tmp_q_1_8x16b;
__m128i coef_8x16b, mask_d_result_4x32b, mask_de_result_8x16b;
__m128i mask_16x8b, temp_coef0_8x16b, temp_coef1_8x16b;
ASSERT((bs > 0));
ASSERT(filter_flag_p || filter_flag_q);
qp_luma = (quant_param_p + quant_param_q + 1) >> 1;
beta_indx = CLIP3(qp_luma + (beta_offset_div2 << 1), 0, 51);
/* BS based on implementation can take value 3 if it is intra/inter egde */
/* based on BS, tc index is calcuated by adding 2 * ( bs - 1) to QP and tc_offset */
/* for BS = 1 adding factor is (0*2), BS = 2 or 3 adding factor is (1*2) */
/* the above desired functionallity is achieved by doing (2*(bs>>1)) */
tc_indx = CLIP3(qp_luma + 2 * (bs >> 1) + (tc_offset_div2 << 1), 0, 53);
beta = gai4_ihevc_beta_table[beta_indx];
tc = gai4_ihevc_tc_table[tc_indx];
if(0 == tc)
{
return;
}
src_q0_8x16b = _mm_loadl_epi64((__m128i *)(pu1_src));
src_q1_8x16b = _mm_loadl_epi64((__m128i *)(pu1_src + src_strd));
src_p0_8x16b = _mm_loadl_epi64((__m128i *)(pu1_src - src_strd));
src_p1_8x16b = _mm_loadl_epi64((__m128i *)(pu1_src - 2 * src_strd));
src_q2_8x16b = _mm_loadl_epi64((__m128i *)(pu1_src + 2 * src_strd));
tmp_pq_str1_8x16b = _mm_loadl_epi64((__m128i *)(pu1_src + 3 * src_strd));
src_p2_8x16b = _mm_loadl_epi64((__m128i *)(pu1_src - 3 * src_strd));
tmp_pq_str0_8x16b = _mm_loadl_epi64((__m128i *)(pu1_src - 4 * src_strd));
src_tmp_p_0_8x16b = _mm_unpacklo_epi8(src_p1_8x16b, src_p0_8x16b);
src_tmp_p_1_8x16b = _mm_unpacklo_epi8(tmp_pq_str0_8x16b, src_p2_8x16b);
src_tmp_q_0_8x16b = _mm_unpacklo_epi8(src_q0_8x16b, src_q1_8x16b);
src_tmp_q_1_8x16b = _mm_unpacklo_epi8(src_q2_8x16b, tmp_pq_str1_8x16b);
src_tmp_p_0_8x16b = _mm_unpacklo_epi16(src_tmp_p_1_8x16b, src_tmp_p_0_8x16b);
src_tmp_q_0_8x16b = _mm_unpacklo_epi16(src_tmp_q_0_8x16b, src_tmp_q_1_8x16b);
src_tmp_p_0_8x16b = _mm_shuffle_epi32(src_tmp_p_0_8x16b, 0x6c);
src_tmp_q_0_8x16b = _mm_shuffle_epi32(src_tmp_q_0_8x16b, 0x6c);
coef_8x16b = _mm_load_si128((__m128i *)(coef_d));
mask_16x8b = _mm_load_si128((__m128i *)(shuffle_d));
src_tmp_p_0_8x16b = _mm_unpacklo_epi32(src_tmp_p_0_8x16b, src_tmp_q_0_8x16b);
//WORD32 shuffle_d[4]={0x80800403,0x80800c0b,0x03000704,0x0b080f0c};
mask_de_result_8x16b = _mm_shuffle_epi8(src_tmp_p_0_8x16b, mask_16x8b);
mask_d_result_4x32b = _mm_maddubs_epi16(src_tmp_p_0_8x16b, coef_8x16b);
//to get all 1's of 8 bit in (1)
temp_coef0_8x16b = _mm_cmpeq_epi16(src_tmp_p_0_8x16b, src_tmp_p_0_8x16b);
temp_coef1_8x16b = _mm_srli_epi16(temp_coef0_8x16b, 15);
//accumulating values foe dp3 dq3 , dp0 dq0 values
mask_d_result_4x32b = _mm_madd_epi16(mask_d_result_4x32b, temp_coef1_8x16b);
temp_coef1_8x16b = _mm_packus_epi16(temp_coef1_8x16b, temp_coef1_8x16b);
// to get all 1,-1 sets of 16 bits in (0)
temp_coef0_8x16b = _mm_unpacklo_epi8(temp_coef0_8x16b, temp_coef1_8x16b);
//q33-q30,p33-p30,q03-q00,p03-p00,0,q30-p30,0,q00-p00
mask_de_result_8x16b = _mm_maddubs_epi16(mask_de_result_8x16b, temp_coef0_8x16b);
//to get 16 bit 1's
temp_coef0_8x16b = _mm_srli_epi16(temp_coef1_8x16b, 8);
// dq3 dp3 dq0 dp0
mask_d_result_4x32b = _mm_abs_epi32(mask_d_result_4x32b);
mask_16x8b = _mm_shuffle_epi32(mask_d_result_4x32b, 0xec);
mask_d_result_4x32b = _mm_shuffle_epi32(mask_d_result_4x32b, 0x49);
// dq dp d3 d0
mask_d_result_4x32b = _mm_add_epi32(mask_d_result_4x32b, mask_16x8b);
//|q33-q30|,|p33-p30|,|q03-q00|,|p03-p00|,0,|q30-p30|,0,|q00-p00|
mask_de_result_8x16b = _mm_abs_epi16(mask_de_result_8x16b);
//|q33-q30|+|p33-p30|,|q03-q00|+|p03-p00|,0+|q30-p30|,0+|q00-p00|
mask_de_result_8x16b = _mm_madd_epi16(mask_de_result_8x16b, temp_coef0_8x16b);
///store back in a single variable
temp_coef0_8x16b = _mm_srli_si128(mask_d_result_4x32b, 4);
temp_coef1_8x16b = _mm_srli_si128(mask_d_result_4x32b, 8);
mask_16x8b = _mm_srli_si128(mask_d_result_4x32b, 12);
d0 = _mm_cvtsi128_si32(mask_d_result_4x32b);
d3 = _mm_cvtsi128_si32(temp_coef0_8x16b);
dp = _mm_cvtsi128_si32(temp_coef1_8x16b);
dq = _mm_cvtsi128_si32(mask_16x8b);
//getting d
d = d0 + d3;
///store back in a single variable
temp_coef0_8x16b = _mm_srli_si128(mask_de_result_8x16b, 4);
temp_coef1_8x16b = _mm_srli_si128(mask_de_result_8x16b, 8);
mask_16x8b = _mm_srli_si128(mask_de_result_8x16b, 12);
de_0 = _mm_cvtsi128_si32(mask_de_result_8x16b);
de_1 = _mm_cvtsi128_si32(temp_coef0_8x16b);
de_2 = _mm_cvtsi128_si32(temp_coef1_8x16b);
de_3 = _mm_cvtsi128_si32(mask_16x8b);
de = 0;
dep = 0;
deq = 0;
if(d < beta)
{
d_sam0 = 0;
if((2 * d0 < (beta >> 2))
&& (de_2 < (beta >> 3))
&& (de_0 < ((5 * tc + 1) >> 1)))
{
d_sam0 = 1;
}
d_sam3 = 0;
if((2 * d3 < (beta >> 2))
&& (de_3 < (beta >> 3))
&& de_1 < ((5 * tc + 1) >> 1))
{
d_sam3 = 1;
}
de = (d_sam0 & d_sam3) + 1;
dep = (dp < (beta + (beta >> 1)) >> 3) ? 1 : 0;
deq = (dq < (beta + (beta >> 1)) >> 3) ? 1 : 0;
if(tc <= 1)
{
dep = 0;
deq = 0;
}
}
}
if(de != 0)
{
if(2 == de)
{
__m128i temp_pq0_str0_16x8b;
__m128i temp_pq1_str0_16x8b, temp_pq1_str1_16x8b;
__m128i temp_pq2_str0_16x8b;
__m128i temp_str0_16x8b, temp_str1_16x8b;
__m128i const2_8x16b, const2tc_8x16b;
LWORD64 mask, tc2;
tc = tc << 1;
mask = (((LWORD64)filter_flag_q) << 63) | (((LWORD64)filter_flag_p) << 31);
tc2 = ((LWORD64)tc);
const2_8x16b = _mm_cmpeq_epi16(src_p1_8x16b, src_p1_8x16b);
//q'0-q'1-2 ,p'0-p'1-2
temp_pq0_str0_16x8b = _mm_unpacklo_epi8(src_p1_8x16b, src_p0_8x16b);
temp_str0_16x8b = _mm_unpacklo_epi8(src_q0_8x16b, src_q1_8x16b);
const2_8x16b = _mm_srli_epi16(const2_8x16b, 15);
//arranged q31 q30 q21 q20 q1 q10 q01 q00 p30 p31 p20 p21 p10 p11 p00 p01
temp_pq0_str0_16x8b = _mm_unpacklo_epi64(temp_pq0_str0_16x8b, temp_str0_16x8b);
const2_8x16b = _mm_packus_epi16(const2_8x16b, const2_8x16b);
temp_pq0_str0_16x8b = _mm_maddubs_epi16(temp_pq0_str0_16x8b, const2_8x16b);
//q'1-2, p'1-2
temp_pq1_str0_16x8b = _mm_unpacklo_epi8(src_p0_8x16b, src_q0_8x16b);
temp_pq1_str1_16x8b = _mm_unpacklo_epi8(src_q1_8x16b, src_q2_8x16b);
temp_str1_16x8b = _mm_unpacklo_epi8(src_p1_8x16b, src_p2_8x16b);
// q30 p30 q20 p20 q10 p10 q01 q00 p30 q20 p20 q10 p10 q01 q00 p00
temp_pq1_str0_16x8b = _mm_unpacklo_epi64(temp_pq1_str0_16x8b, temp_pq1_str0_16x8b);
// q32 q31 q22 q21 q12 q11 q02 q01 p32 p31 p22 p21 p12 p11 p02 p01
temp_pq1_str1_16x8b = _mm_unpacklo_epi64(temp_str1_16x8b, temp_pq1_str1_16x8b);
temp_pq1_str0_16x8b = _mm_maddubs_epi16(temp_pq1_str0_16x8b, const2_8x16b);
temp_pq1_str1_16x8b = _mm_maddubs_epi16(temp_pq1_str1_16x8b, const2_8x16b);
//clipping mask design
temp_str1_16x8b = _mm_setzero_si128();
temp_str0_16x8b = _mm_loadl_epi64((__m128i *)(&mask));
const2tc_8x16b = _mm_loadl_epi64((__m128i *)(&tc2));
temp_str0_16x8b = _mm_shuffle_epi32(temp_str0_16x8b, 0x44);
const2tc_8x16b = _mm_shuffle_epi8(const2tc_8x16b, temp_str1_16x8b);
//clipping mask design
temp_str0_16x8b = _mm_srai_epi32(temp_str0_16x8b, 31);
const2tc_8x16b = _mm_and_si128(const2tc_8x16b, temp_str0_16x8b);
//calculating Clipping MAX for all pixel values.
src_p0_8x16b = _mm_unpacklo_epi32(src_p0_8x16b, src_q0_8x16b);
src_q0_8x16b = _mm_unpacklo_epi32(src_p1_8x16b, src_q1_8x16b);
//for clipping calc
src_p1_8x16b = _mm_unpacklo_epi64(src_p0_8x16b, src_q0_8x16b);
//saving the unmodified data of q1 p1 q0 p0
src_q1_8x16b = _mm_unpackhi_epi64(src_p0_8x16b, src_q0_8x16b);
//CLIpping MAX and MIN for q1 p1 q0 p0
src_p0_8x16b = _mm_adds_epu8(src_p1_8x16b, const2tc_8x16b);
src_p1_8x16b = _mm_subs_epu8(src_p1_8x16b, const2tc_8x16b);
//q'2-q'0-2,p'2-p'0-2
tmp_pq_str0_8x16b = _mm_unpacklo_epi8(src_p2_8x16b, tmp_pq_str0_8x16b);
temp_pq2_str0_16x8b = _mm_unpacklo_epi8(src_q2_8x16b, tmp_pq_str1_8x16b);
const2_8x16b = _mm_slli_epi16(const2_8x16b, 1);
//arranged q33 q32 q23 q22 q13 q12 q03 q02 p32 p33 p22 p23 p12 p13 p02 p03
temp_pq2_str0_16x8b = _mm_unpacklo_epi64(tmp_pq_str0_8x16b, temp_pq2_str0_16x8b);
src_p2_8x16b = _mm_unpacklo_epi32(src_p2_8x16b, src_q2_8x16b);
temp_pq2_str0_16x8b = _mm_maddubs_epi16(temp_pq2_str0_16x8b, const2_8x16b);
//calculating Clipping MAX and MIN for p2 and q2 .
tmp_pq_str0_8x16b = _mm_adds_epu8(src_p2_8x16b, const2tc_8x16b);
tmp_pq_str1_8x16b = _mm_subs_epu8(src_p2_8x16b, const2tc_8x16b);
//q'0-q'1-2 ,p'0-p'1-2
temp_str0_16x8b = _mm_shuffle_epi32(temp_pq0_str0_16x8b, 0x4e);
temp_pq0_str0_16x8b = _mm_add_epi16(temp_pq0_str0_16x8b, temp_str0_16x8b);
//q'1-2 p'1-2
temp_pq1_str0_16x8b = _mm_add_epi16(temp_pq1_str0_16x8b, temp_pq1_str1_16x8b);
//to get 2 in 16 bit
const2_8x16b = _mm_srli_epi16(const2_8x16b, 8);
//q'1, p'1 (adding 2)
temp_pq1_str0_16x8b = _mm_add_epi16(temp_pq1_str0_16x8b, const2_8x16b);
//q'0-q'1,p'0-p'1
temp_pq0_str0_16x8b = _mm_add_epi16(temp_pq0_str0_16x8b, const2_8x16b);
//q'2-q'1,p'2-p'1
temp_pq2_str0_16x8b = _mm_add_epi16(temp_pq2_str0_16x8b, const2_8x16b);
//q'0 = (q'0-q'1)+q'1 ,p'0 = (p'0-p'1)+p'1;
temp_pq0_str0_16x8b = _mm_add_epi16(temp_pq1_str0_16x8b, temp_pq0_str0_16x8b);
//q'2 = (q'2-q'1)+q'1 ,p'2 = (p'2-p'1)+p'1;
temp_pq2_str0_16x8b = _mm_add_epi16(temp_pq1_str0_16x8b, temp_pq2_str0_16x8b);
//normalisation of all modified pixels
temp_pq0_str0_16x8b = _mm_srai_epi16(temp_pq0_str0_16x8b, 3);
temp_pq1_str0_16x8b = _mm_srai_epi16(temp_pq1_str0_16x8b, 2);
temp_pq2_str0_16x8b = _mm_srai_epi16(temp_pq2_str0_16x8b, 3);
//q'1 p'1 q'0 p'0
temp_pq0_str0_16x8b = _mm_packus_epi16(temp_pq0_str0_16x8b, temp_pq1_str0_16x8b);
temp_pq2_str0_16x8b = _mm_packus_epi16(temp_pq2_str0_16x8b, temp_pq2_str0_16x8b);
//pack with the unmodified data of q2 and p2
src_p2_8x16b = _mm_unpackhi_epi64(temp_pq2_str0_16x8b, src_p2_8x16b);
//Clipping MAX and MIN for q'1 p'1 q'0 p'0 and q'2 p'2
temp_pq0_str0_16x8b = _mm_min_epu8(temp_pq0_str0_16x8b, src_p0_8x16b);
src_p2_8x16b = _mm_min_epu8(src_p2_8x16b, tmp_pq_str0_8x16b);
temp_pq0_str0_16x8b = _mm_max_epu8(temp_pq0_str0_16x8b, src_p1_8x16b);
src_p2_8x16b = _mm_max_epu8(src_p2_8x16b, tmp_pq_str1_8x16b);
//Reshuffling q'1 p'1 q'0 p'0 along with unmodified data
src_p0_8x16b = _mm_unpacklo_epi32(temp_pq0_str0_16x8b, src_q1_8x16b);
src_p1_8x16b = _mm_unpackhi_epi32(temp_pq0_str0_16x8b, src_q1_8x16b);
src_p2_8x16b = _mm_shuffle_epi32(src_p2_8x16b, 0xd8);
src_q0_8x16b = _mm_srli_si128(src_p0_8x16b, 8);
src_q1_8x16b = _mm_srli_si128(src_p1_8x16b, 8);
src_q2_8x16b = _mm_srli_si128(src_p2_8x16b, 8);
_mm_storel_epi64((__m128i *)(pu1_src - 3 * src_strd), src_p2_8x16b);
_mm_storel_epi64((__m128i *)(pu1_src - 2 * src_strd), src_p1_8x16b);
_mm_storel_epi64((__m128i *)(pu1_src - src_strd), src_p0_8x16b);
_mm_storel_epi64((__m128i *)(pu1_src), src_q0_8x16b);
_mm_storel_epi64((__m128i *)(pu1_src + src_strd), src_q1_8x16b);
_mm_storel_epi64((__m128i *)(pu1_src + 2 * src_strd), src_q2_8x16b);
}
else
{
__m128i tmp_delta0_8x16b, tmp_delta1_8x16b;
__m128i tmp0_const_8x16b, tmp1_const_8x16b, tmp2_const_8x16b;
__m128i coefdelta_0_8x16b;
__m128i const2_8x16b, consttc_8x16b;
LWORD64 maskp0, maskp1, maskq0, maskq1;
maskp0 = (LWORD64)filter_flag_p;
maskq0 = (LWORD64)filter_flag_q;
maskp1 = (LWORD64)dep;
maskq1 = (LWORD64)deq;
consttc_8x16b = _mm_set1_epi32(tc);
tmp_delta0_8x16b = _mm_unpacklo_epi8(src_p1_8x16b, src_p0_8x16b);
tmp_delta1_8x16b = _mm_unpacklo_epi8(src_q0_8x16b, src_q1_8x16b);
//arranged q31 q30 p30 p31 q21 q20 p20 p21 q1 q10 p10 p11 q01 q00 p00 p01
tmp_delta1_8x16b = _mm_unpacklo_epi16(tmp_delta0_8x16b, tmp_delta1_8x16b);
coefdelta_0_8x16b = _mm_load_si128((__m128i *)coef_de1);
// (-3q1+9q0),(-9p0+3p1)
tmp_delta0_8x16b = _mm_maddubs_epi16(tmp_delta1_8x16b, coefdelta_0_8x16b);
//getting -tc store
tmp2_const_8x16b = _mm_cmpeq_epi32(consttc_8x16b, consttc_8x16b);
//getting tc in 16 bit
consttc_8x16b = _mm_packs_epi32(consttc_8x16b, consttc_8x16b);
//calc 10 *tc = 2*tc +8*tc ; 2*tc
tmp_pq_str0_8x16b = _mm_slli_epi16(consttc_8x16b, 1);
//calc 10 *tc = 2*tc +8*tc ; 8*tc
tmp_pq_str1_8x16b = _mm_slli_epi16(consttc_8x16b, 3);
//const 1
const2_8x16b = _mm_srli_epi16(tmp2_const_8x16b, 15);
//calc 10 *tc
tmp_pq_str0_8x16b = _mm_add_epi16(tmp_pq_str0_8x16b, tmp_pq_str1_8x16b);
//delta0 without normalisation and clipping
tmp_delta0_8x16b = _mm_madd_epi16(tmp_delta0_8x16b, const2_8x16b);
const2_8x16b = _mm_srli_epi32(tmp2_const_8x16b, 31);
//loaded coef for delta1 calculation
coefdelta_0_8x16b = _mm_load_si128((__m128i *)coef_dep1);
//(-2q1+q0),(p0-2p1)
tmp_delta1_8x16b = _mm_maddubs_epi16(tmp_delta1_8x16b, coefdelta_0_8x16b);
//const 8
const2_8x16b = _mm_slli_epi32(const2_8x16b, 3);
//normalisation of the filter
tmp_delta0_8x16b = _mm_add_epi32(tmp_delta0_8x16b, const2_8x16b);
tmp_delta0_8x16b = _mm_srai_epi32(tmp_delta0_8x16b, 4);
//getting deltaq0
tmp_pq_str1_8x16b = _mm_sign_epi32(tmp_delta0_8x16b, tmp2_const_8x16b);
//getting -tc
tmp1_const_8x16b = _mm_sign_epi16(consttc_8x16b, tmp2_const_8x16b);
//packing d03q d02q d01q d0q d03p d02p d01p d00p
tmp_delta0_8x16b = _mm_packs_epi32(tmp_delta0_8x16b, tmp_pq_str1_8x16b);
//absolute delta
tmp_pq_str1_8x16b = _mm_abs_epi16(tmp_delta0_8x16b);
//Clipping of delta0
tmp_delta0_8x16b = _mm_min_epi16(tmp_delta0_8x16b, consttc_8x16b);
//tc>>1 16 bit
consttc_8x16b = _mm_srai_epi16(consttc_8x16b, 1);
//Clipping of delta0
tmp_delta0_8x16b = _mm_max_epi16(tmp_delta0_8x16b, tmp1_const_8x16b);
//(-tc)>>1 16 bit
tmp1_const_8x16b = _mm_sign_epi16(consttc_8x16b, tmp2_const_8x16b);
//mask for |delta| < 10*tc
tmp_pq_str0_8x16b = _mm_cmpgt_epi16(tmp_pq_str0_8x16b, tmp_pq_str1_8x16b);
//delta 1 calc starts
//getting q32 q22 q12 q02 p32 p12 p22 p02
tmp0_const_8x16b = _mm_setzero_si128();
src_q2_8x16b = _mm_unpacklo_epi8(src_q2_8x16b, tmp0_const_8x16b);
src_p2_8x16b = _mm_unpacklo_epi8(src_p2_8x16b, tmp0_const_8x16b);
src_p2_8x16b = _mm_unpacklo_epi64(src_p2_8x16b, src_q2_8x16b);
//constant 1
const2_8x16b = _mm_srli_epi16(tmp2_const_8x16b, 15);
//2*delta0
tmp2_const_8x16b = _mm_add_epi16(tmp_delta0_8x16b, tmp_delta0_8x16b);
//getting all respective q's and p's together
coefdelta_0_8x16b = _mm_load_si128((__m128i *)(shuffle1));
tmp_delta1_8x16b = _mm_shuffle_epi8(tmp_delta1_8x16b, coefdelta_0_8x16b);
//final adds for deltap1 and deltaq1
tmp_delta1_8x16b = _mm_add_epi16(tmp_delta1_8x16b, const2_8x16b);
src_p2_8x16b = _mm_add_epi16(src_p2_8x16b, tmp2_const_8x16b);
tmp_delta1_8x16b = _mm_add_epi16(tmp_delta1_8x16b, src_p2_8x16b);
tmp_delta1_8x16b = _mm_srai_epi16(tmp_delta1_8x16b, 2);
//mask0= (((LWORD64)filter_flag_q)<<63)| (((LWORD64)filter_flag_p)<<31);
tmp_pq_str1_8x16b = _mm_loadl_epi64((__m128i *)(&(maskq0)));
src_p2_8x16b = _mm_loadl_epi64((__m128i *)(&(maskp0)));
// src_p2_8x16b = _mm_set_epi32(filter_flag_q,filter_flag_p,filter_flag_q,filter_flag_p);
//mask1= (((LWORD64)(filter_flag_q&deq))<<63)|(((LWORD64)(filter_flag_p & dep))<<31);
src_q2_8x16b = _mm_loadl_epi64((__m128i *)(&(maskq1)));
coefdelta_0_8x16b = _mm_loadl_epi64((__m128i *)(&(maskp1)));
src_p2_8x16b = _mm_unpacklo_epi32(src_p2_8x16b, tmp_pq_str1_8x16b);
src_q2_8x16b = _mm_unpacklo_epi32(coefdelta_0_8x16b, src_q2_8x16b);
//src_q2_8x16b = _mm_set_epi32(deq,dep,deq,dep);
src_q2_8x16b = _mm_and_si128(src_q2_8x16b, src_p2_8x16b);
//rearranging the mask values
src_q2_8x16b = _mm_shuffle_epi32(src_q2_8x16b, 0x50);
src_p2_8x16b = _mm_shuffle_epi32(src_p2_8x16b, 0x50);
src_q2_8x16b = _mm_slli_epi32(src_q2_8x16b, 31);
src_p2_8x16b = _mm_slli_epi32(src_p2_8x16b, 31);
src_q2_8x16b = _mm_srai_epi32(src_q2_8x16b, 31);
src_p2_8x16b = _mm_srai_epi32(src_p2_8x16b, 31);
//combining mask delta1
tmp_pq_str1_8x16b = _mm_and_si128(tmp_pq_str0_8x16b, src_q2_8x16b);
// clipping delta1
tmp_delta1_8x16b = _mm_min_epi16(tmp_delta1_8x16b, consttc_8x16b);
//combining mask delat0
tmp_pq_str0_8x16b = _mm_and_si128(tmp_pq_str0_8x16b, src_p2_8x16b);
// clipping delta1
tmp_delta1_8x16b = _mm_max_epi16(tmp_delta1_8x16b, tmp1_const_8x16b);
//masking of the delta values |delta|<10*tc
tmp_delta1_8x16b = _mm_and_si128(tmp_delta1_8x16b, tmp_pq_str1_8x16b);
tmp_delta0_8x16b = _mm_and_si128(tmp_delta0_8x16b, tmp_pq_str0_8x16b);
//separating p and q delta 0 and addinq p0 and q0
tmp_pq_str0_8x16b = _mm_unpacklo_epi64(tmp_delta0_8x16b, tmp0_const_8x16b);
tmp_pq_str1_8x16b = _mm_unpackhi_epi64(tmp_delta0_8x16b, tmp0_const_8x16b);
src_p0_8x16b = _mm_unpacklo_epi8(src_p0_8x16b, tmp0_const_8x16b);
src_q0_8x16b = _mm_unpacklo_epi8(src_q0_8x16b, tmp0_const_8x16b);
src_p0_8x16b = _mm_add_epi16(src_p0_8x16b, tmp_pq_str0_8x16b);
src_q0_8x16b = _mm_add_epi16(src_q0_8x16b, tmp_pq_str1_8x16b);
//separating p and q delta 0 and addinq p0 and q0
tmp_pq_str0_8x16b = _mm_unpacklo_epi64(tmp_delta1_8x16b, tmp0_const_8x16b);
tmp_pq_str1_8x16b = _mm_unpackhi_epi64(tmp_delta1_8x16b, tmp0_const_8x16b);
src_p1_8x16b = _mm_unpacklo_epi8(src_p1_8x16b, tmp0_const_8x16b);
src_q1_8x16b = _mm_unpacklo_epi8(src_q1_8x16b, tmp0_const_8x16b);
src_p1_8x16b = _mm_add_epi16(src_p1_8x16b, tmp_pq_str0_8x16b);
src_q1_8x16b = _mm_add_epi16(src_q1_8x16b, tmp_pq_str1_8x16b);
//packing p1 q1 and p0 q0 to 8 bit
src_p1_8x16b = _mm_packus_epi16(src_p1_8x16b, src_q1_8x16b);
src_p0_8x16b = _mm_packus_epi16(src_p0_8x16b, src_q0_8x16b);
src_q1_8x16b = _mm_srli_si128(src_p1_8x16b, 8);
src_q0_8x16b = _mm_srli_si128(src_p0_8x16b, 8);
_mm_storel_epi64((__m128i *)(pu1_src - 2 * src_strd), src_p1_8x16b);
_mm_storel_epi64((__m128i *)(pu1_src - src_strd), src_p0_8x16b);
_mm_storel_epi64((__m128i *)(pu1_src), src_q0_8x16b);
_mm_storel_epi64((__m128i *)(pu1_src + src_strd), src_q1_8x16b);
}
}
}
void ihevc_deblk_chroma_vert_ssse3(UWORD8 *pu1_src,
WORD32 src_strd,
WORD32 quant_param_p,
WORD32 quant_param_q,
WORD32 qp_offset_u,
WORD32 qp_offset_v,
WORD32 tc_offset_div2,
WORD32 filter_flag_p,
WORD32 filter_flag_q)
{
WORD32 qp_indx_u, qp_chroma_u;
WORD32 qp_indx_v, qp_chroma_v;
WORD32 tc_indx_u, tc_u;
WORD32 tc_indx_v, tc_v;
__m128i src_row_0_16x8b, tmp_pxl_0_16x8b, src_row_2_16x8b, tmp_pxl_1_16x8b;
ASSERT(filter_flag_p || filter_flag_q);
/* chroma processing is done only if BS is 2 */
/* this function is assumed to be called only if BS is 2 */
qp_indx_u = qp_offset_u + ((quant_param_p + quant_param_q + 1) >> 1);
qp_chroma_u = qp_indx_u < 0 ? qp_indx_u : (qp_indx_u > 57 ? qp_indx_u - 6 : gai4_ihevc_qp_table[qp_indx_u]);
qp_indx_v = qp_offset_v + ((quant_param_p + quant_param_q + 1) >> 1);
qp_chroma_v = qp_indx_v < 0 ? qp_indx_v : (qp_indx_v > 57 ? qp_indx_v - 6 : gai4_ihevc_qp_table[qp_indx_v]);
tc_indx_u = CLIP3(qp_chroma_u + 2 + (tc_offset_div2 << 1), 0, 53);
tc_u = gai4_ihevc_tc_table[tc_indx_u];
tc_indx_v = CLIP3(qp_chroma_v + 2 + (tc_offset_div2 << 1), 0, 53);
tc_v = gai4_ihevc_tc_table[tc_indx_v];
if(0 == tc_u && 0 == tc_v)
{
return;
}
src_row_0_16x8b = _mm_loadl_epi64((__m128i *)(pu1_src - 4));
tmp_pxl_0_16x8b = _mm_loadl_epi64((__m128i *)(pu1_src + src_strd - 4));
src_row_2_16x8b = _mm_loadl_epi64((__m128i *)(pu1_src + 2 * src_strd - 4));
tmp_pxl_1_16x8b = _mm_loadl_epi64((__m128i *)(pu1_src + 3 * src_strd - 4));
{
LWORD64 mask_tc, mask_flag, mask;
__m128i delta_vu0_16x8b, delta_vu1_16x8b;
__m128i mask_tc_16x8, mask_16x8b, mask_flag_p_16x8b, mask_flag_q_16x8b;
__m128i min_0_16x8b;
__m128i const_16x8b;
mask_flag = (((LWORD64)filter_flag_p) << 31) | (((LWORD64)filter_flag_q) << 63);
mask_tc = (((LWORD64)tc_v) << 16) | ((LWORD64)tc_u);
mask = 0xffff00000000ffffLL;
src_row_0_16x8b = _mm_unpacklo_epi64(src_row_0_16x8b, tmp_pxl_0_16x8b);
src_row_2_16x8b = _mm_unpacklo_epi64(src_row_2_16x8b, tmp_pxl_1_16x8b);
mask_16x8b = _mm_load_si128((__m128i *)(shuffle_uv));
// qv11 qu11 qv10 qu10 qv01 qu01 qv00 qu00 pv10 pu10 pv11 pu11 pv00 pu00 pv01 pu01
// qv31 qu31 qv30 qu30 qv21 qu21 qv20 qu20 pv30 pu30 pv31 pu31 pv20 pu20 pv21 pu21
delta_vu0_16x8b = _mm_shuffle_epi8(src_row_0_16x8b, mask_16x8b);
delta_vu1_16x8b = _mm_shuffle_epi8(src_row_2_16x8b, mask_16x8b);
tmp_pxl_0_16x8b = _mm_unpacklo_epi64(delta_vu0_16x8b, delta_vu1_16x8b);
tmp_pxl_1_16x8b = _mm_unpackhi_epi64(delta_vu0_16x8b, delta_vu1_16x8b);
// pv30 pv31 pu30 pu31 pv20 pv21 pu20 pu21 pv10 pv11 pu10 pu11 pv00 pv01 pu00 pu01
// qv31 qv30 qu31 qu30 qv21 qv20 qu21 qu20 qv11 qv10 qu11 qu10 qv01 qv00 qu01 qu00
delta_vu0_16x8b = _mm_load_si128((__m128i *)delta0);
delta_vu1_16x8b = _mm_load_si128((__m128i *)delta1);
delta_vu0_16x8b = _mm_maddubs_epi16(tmp_pxl_0_16x8b, delta_vu0_16x8b);
delta_vu1_16x8b = _mm_maddubs_epi16(tmp_pxl_1_16x8b, delta_vu1_16x8b);
//generating offset 4
const_16x8b = _mm_cmpeq_epi16(tmp_pxl_0_16x8b, tmp_pxl_0_16x8b);
// filter flag mask and tc mask
mask_tc_16x8 = _mm_loadl_epi64((__m128i *)(&mask_tc));
mask_flag_q_16x8b = _mm_loadl_epi64((__m128i *)(&mask_flag));
mask_tc_16x8 = _mm_shuffle_epi32(mask_tc_16x8, 0x00);
mask_flag_q_16x8b = _mm_srai_epi32(mask_flag_q_16x8b, 31);
//-tc
min_0_16x8b = _mm_sign_epi16(mask_tc_16x8, const_16x8b);
//converting const 1
const_16x8b = _mm_srli_epi16(const_16x8b, 15);
//filterp and filterq flag
mask_flag_p_16x8b = _mm_shuffle_epi32(mask_flag_q_16x8b, 0x00);
mask_flag_q_16x8b = _mm_shuffle_epi32(mask_flag_q_16x8b, 0x55);
//modified delta with a filter (1 -4 4 -1) available in 16 bit
delta_vu0_16x8b = _mm_add_epi16(delta_vu0_16x8b, delta_vu1_16x8b);
//converting const 4
const_16x8b = _mm_slli_epi16(const_16x8b, 2);
mask_16x8b = _mm_loadl_epi64((__m128i *)(&mask));
//offset addition
delta_vu0_16x8b = _mm_add_epi16(delta_vu0_16x8b, const_16x8b);
//eliminating q1
tmp_pxl_1_16x8b = _mm_slli_epi16(tmp_pxl_1_16x8b, 8);
const_16x8b = _mm_setzero_si128();
//filter after normalisation
delta_vu0_16x8b = _mm_srai_epi16(delta_vu0_16x8b, 3);
mask_16x8b = _mm_shuffle_epi32(mask_16x8b, 0x44);
//clipping MAX
delta_vu0_16x8b = _mm_min_epi16(delta_vu0_16x8b, mask_tc_16x8);
//getting p0 and eliminating p1
tmp_pxl_0_16x8b = _mm_srli_epi16(tmp_pxl_0_16x8b, 8);
//clipping MIN
delta_vu0_16x8b = _mm_max_epi16(delta_vu0_16x8b, min_0_16x8b);
//getting q0
tmp_pxl_1_16x8b = _mm_srli_epi16(tmp_pxl_1_16x8b, 8);
//masking filter flag
delta_vu1_16x8b = _mm_and_si128(delta_vu0_16x8b, mask_flag_q_16x8b);
delta_vu0_16x8b = _mm_and_si128(delta_vu0_16x8b, mask_flag_p_16x8b);
// q-delta ,p+delta
tmp_pxl_1_16x8b = _mm_sub_epi16(tmp_pxl_1_16x8b, delta_vu1_16x8b);
tmp_pxl_0_16x8b = _mm_add_epi16(tmp_pxl_0_16x8b, delta_vu0_16x8b);
//merging q0 and p0 of respective rows
delta_vu1_16x8b = _mm_unpackhi_epi32(tmp_pxl_0_16x8b, tmp_pxl_1_16x8b);
delta_vu0_16x8b = _mm_unpacklo_epi32(tmp_pxl_0_16x8b, tmp_pxl_1_16x8b);
// row 0 and row 1 packed , row2 and row3 packed
delta_vu0_16x8b = _mm_packus_epi16(delta_vu0_16x8b, const_16x8b);
delta_vu1_16x8b = _mm_packus_epi16(delta_vu1_16x8b, const_16x8b);
//removing older pixel values
src_row_0_16x8b = _mm_and_si128(src_row_0_16x8b, mask_16x8b);
src_row_2_16x8b = _mm_and_si128(src_row_2_16x8b, mask_16x8b);
//arranging modified pixels
delta_vu0_16x8b = _mm_shuffle_epi32(delta_vu0_16x8b, 0xd8);
delta_vu1_16x8b = _mm_shuffle_epi32(delta_vu1_16x8b, 0xd8);
delta_vu0_16x8b = _mm_slli_epi64(delta_vu0_16x8b, 16);
delta_vu1_16x8b = _mm_slli_epi64(delta_vu1_16x8b, 16);
//plugging the modified values
src_row_0_16x8b = _mm_or_si128(src_row_0_16x8b, delta_vu0_16x8b);
src_row_2_16x8b = _mm_or_si128(src_row_2_16x8b, delta_vu1_16x8b);
//geting values for row1 and row 3
tmp_pxl_0_16x8b = _mm_srli_si128(src_row_0_16x8b, 8);
tmp_pxl_1_16x8b = _mm_srli_si128(src_row_2_16x8b, 8);
_mm_storel_epi64((__m128i *)(pu1_src - 4), src_row_0_16x8b);
_mm_storel_epi64((__m128i *)((pu1_src - 4) + src_strd), tmp_pxl_0_16x8b);
_mm_storel_epi64((__m128i *)((pu1_src - 4) + 2 * src_strd), src_row_2_16x8b);
_mm_storel_epi64((__m128i *)((pu1_src - 4) + 3 * src_strd), tmp_pxl_1_16x8b);
}
}
void ihevc_deblk_chroma_horz_ssse3(UWORD8 *pu1_src,
WORD32 src_strd,
WORD32 quant_param_p,
WORD32 quant_param_q,
WORD32 qp_offset_u,
WORD32 qp_offset_v,
WORD32 tc_offset_div2,
WORD32 filter_flag_p,
WORD32 filter_flag_q)
{
WORD32 qp_indx_u, qp_chroma_u;
WORD32 qp_indx_v, qp_chroma_v;
WORD32 tc_indx_u, tc_u;
WORD32 tc_indx_v, tc_v;
__m128i tmp_p0_16x8b, src_p0_16x8b, src_q0_16x8b, tmp_q0_16x8b;
ASSERT(filter_flag_p || filter_flag_q);
/* chroma processing is done only if BS is 2 */
/* this function is assumed to be called only if BS is 2 */
qp_indx_u = qp_offset_u + ((quant_param_p + quant_param_q + 1) >> 1);
qp_chroma_u = qp_indx_u < 0 ? qp_indx_u : (qp_indx_u > 57 ? qp_indx_u - 6 : gai4_ihevc_qp_table[qp_indx_u]);
qp_indx_v = qp_offset_v + ((quant_param_p + quant_param_q + 1) >> 1);
qp_chroma_v = qp_indx_v < 0 ? qp_indx_v : (qp_indx_v > 57 ? qp_indx_v - 6 : gai4_ihevc_qp_table[qp_indx_v]);
tc_indx_u = CLIP3(qp_chroma_u + 2 + (tc_offset_div2 << 1), 0, 53);
tc_u = gai4_ihevc_tc_table[tc_indx_u];
tc_indx_v = CLIP3(qp_chroma_v + 2 + (tc_offset_div2 << 1), 0, 53);
tc_v = gai4_ihevc_tc_table[tc_indx_v];
if(0 == tc_u && 0 == tc_v)
{
return;
}
tmp_p0_16x8b = _mm_loadl_epi64((__m128i *)(pu1_src - 2 * src_strd));
src_p0_16x8b = _mm_loadl_epi64((__m128i *)(pu1_src - src_strd));
src_q0_16x8b = _mm_loadl_epi64((__m128i *)(pu1_src));
tmp_q0_16x8b = _mm_loadl_epi64((__m128i *)(pu1_src + src_strd));
{
LWORD64 mask_tc, mask_flag;
__m128i delta_vu0_16x8b, delta_vu1_16x8b;
__m128i mask_tc_16x8, mask_16x8b, mask_flag_p_16x8b, mask_flag_q_16x8b;
__m128i min_0_16x8b;
__m128i const_16x8b;
mask_flag = (((LWORD64)filter_flag_p) << 31) | (((LWORD64)filter_flag_q) << 63);
mask_tc = (((LWORD64)tc_v) << 16) | ((LWORD64)tc_u);
tmp_p0_16x8b = _mm_unpacklo_epi8(tmp_p0_16x8b, src_p0_16x8b);
tmp_q0_16x8b = _mm_unpacklo_epi8(src_q0_16x8b, tmp_q0_16x8b);
// pv30 pv31 pu30 pu31 pv20 pv21 pu20 pu21 pv10 pv11 pu10 pu11 pv00 pv01 pu00 pu01
// qv31 qv30 qu31 qu30 qv21 qv20 qu21 qu20 qv11 qv10 qu11 qu10 qv01 qv00 qu01 qu00
delta_vu0_16x8b = _mm_load_si128((__m128i *)delta0);
delta_vu1_16x8b = _mm_load_si128((__m128i *)delta1);
delta_vu0_16x8b = _mm_maddubs_epi16(tmp_p0_16x8b, delta_vu0_16x8b);
delta_vu1_16x8b = _mm_maddubs_epi16(tmp_q0_16x8b, delta_vu1_16x8b);
// filter flag mask and tc mask
mask_tc_16x8 = _mm_loadl_epi64((__m128i *)(&mask_tc));
mask_flag_q_16x8b = _mm_loadl_epi64((__m128i *)(&mask_flag));
//generating offset 4
const_16x8b = _mm_cmpeq_epi16(tmp_p0_16x8b, tmp_p0_16x8b);
// filter flag mask and tc mask
mask_tc_16x8 = _mm_shuffle_epi32(mask_tc_16x8, 0x00);
mask_flag_q_16x8b = _mm_srai_epi32(mask_flag_q_16x8b, 31);
//-tc
min_0_16x8b = _mm_sign_epi16(mask_tc_16x8, const_16x8b);
//converting const 1
const_16x8b = _mm_srli_epi16(const_16x8b, 15);
//filterp
mask_flag_p_16x8b = _mm_shuffle_epi32(mask_flag_q_16x8b, 0x00);
//converting const 4
const_16x8b = _mm_slli_epi16(const_16x8b, 2);
//modified delta with a filter (1 -4 4 -1) available in 16 bit
delta_vu0_16x8b = _mm_add_epi16(delta_vu0_16x8b, delta_vu1_16x8b);
//filterq flag
mask_flag_q_16x8b = _mm_shuffle_epi32(mask_flag_q_16x8b, 0x55);
//offset addition
delta_vu0_16x8b = _mm_add_epi16(delta_vu0_16x8b, const_16x8b);
mask_16x8b = _mm_setzero_si128();
//filter after normalisation
delta_vu0_16x8b = _mm_srai_epi16(delta_vu0_16x8b, 3);
//converting p0 to 16bit
src_p0_16x8b = _mm_unpacklo_epi8(src_p0_16x8b, mask_16x8b);
//clipping MAX
delta_vu0_16x8b = _mm_min_epi16(delta_vu0_16x8b, mask_tc_16x8);
//converting q0 to 16bit
src_q0_16x8b = _mm_unpacklo_epi8(src_q0_16x8b, mask_16x8b);
//clipping MIN
delta_vu0_16x8b = _mm_max_epi16(delta_vu0_16x8b, min_0_16x8b);
//masking filter flag
delta_vu1_16x8b = _mm_and_si128(delta_vu0_16x8b, mask_flag_q_16x8b);
delta_vu0_16x8b = _mm_and_si128(delta_vu0_16x8b, mask_flag_p_16x8b);
// q-delta ,p+delta
src_q0_16x8b = _mm_sub_epi16(src_q0_16x8b, delta_vu1_16x8b);
src_p0_16x8b = _mm_add_epi16(src_p0_16x8b, delta_vu0_16x8b);
// p0 and q0 packed
src_q0_16x8b = _mm_packus_epi16(src_q0_16x8b, mask_16x8b);
src_p0_16x8b = _mm_packus_epi16(src_p0_16x8b, mask_16x8b);
_mm_storel_epi64((__m128i *)(pu1_src - src_strd), src_p0_16x8b);
_mm_storel_epi64((__m128i *)(pu1_src), src_q0_16x8b);
}
}