| /****************************************************************************** |
| * |
| * 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); |
| |
| } |
| |
| |
| } |