quantize_sse2.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. /*
  2. * Copyright (c) 2015 The WebM project authors. All Rights Reserved.
  3. *
  4. * Use of this source code is governed by a BSD-style license
  5. * that can be found in the LICENSE file in the root of the source
  6. * tree. An additional intellectual property rights grant can be found
  7. * in the file PATENTS. All contributing project authors may
  8. * be found in the AUTHORS file in the root of the source tree.
  9. */
  10. #include <assert.h>
  11. #include <emmintrin.h>
  12. #include <xmmintrin.h>
  13. #include "./vpx_dsp_rtcd.h"
  14. #include "vpx/vpx_integer.h"
  15. #include "vpx_dsp/x86/bitdepth_conversion_sse2.h"
  16. void vpx_quantize_b_sse2(const tran_low_t *coeff_ptr, intptr_t n_coeffs,
  17. int skip_block, const int16_t *zbin_ptr,
  18. const int16_t *round_ptr, const int16_t *quant_ptr,
  19. const int16_t *quant_shift_ptr, tran_low_t *qcoeff_ptr,
  20. tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr,
  21. uint16_t *eob_ptr, const int16_t *scan_ptr,
  22. const int16_t *iscan_ptr) {
  23. const __m128i zero = _mm_setzero_si128();
  24. int index = 16;
  25. __m128i zbin, round, quant, dequant, shift;
  26. __m128i coeff0, coeff1, coeff0_sign, coeff1_sign;
  27. __m128i qcoeff0, qcoeff1;
  28. __m128i cmp_mask0, cmp_mask1;
  29. __m128i qtmp0, qtmp1;
  30. __m128i zero_coeff0, zero_coeff1, iscan0, iscan1;
  31. __m128i eob, eob0, eob1;
  32. (void)scan_ptr;
  33. (void)skip_block;
  34. assert(!skip_block);
  35. // Setup global values.
  36. zbin = _mm_load_si128((const __m128i *)zbin_ptr);
  37. round = _mm_load_si128((const __m128i *)round_ptr);
  38. quant = _mm_load_si128((const __m128i *)quant_ptr);
  39. zbin = _mm_sub_epi16(zbin, _mm_set1_epi16(1));
  40. dequant = _mm_load_si128((const __m128i *)dequant_ptr);
  41. shift = _mm_load_si128((const __m128i *)quant_shift_ptr);
  42. // Do DC and first 15 AC.
  43. coeff0 = load_tran_low(coeff_ptr);
  44. coeff1 = load_tran_low(coeff_ptr + 8);
  45. // Poor man's abs().
  46. coeff0_sign = _mm_srai_epi16(coeff0, 15);
  47. coeff1_sign = _mm_srai_epi16(coeff1, 15);
  48. qcoeff0 = _mm_xor_si128(coeff0, coeff0_sign);
  49. qcoeff1 = _mm_xor_si128(coeff1, coeff1_sign);
  50. qcoeff0 = _mm_sub_epi16(qcoeff0, coeff0_sign);
  51. qcoeff1 = _mm_sub_epi16(qcoeff1, coeff1_sign);
  52. cmp_mask0 = _mm_cmpgt_epi16(qcoeff0, zbin);
  53. zbin = _mm_unpackhi_epi64(zbin, zbin); // Switch DC to AC
  54. cmp_mask1 = _mm_cmpgt_epi16(qcoeff1, zbin);
  55. qcoeff0 = _mm_adds_epi16(qcoeff0, round);
  56. round = _mm_unpackhi_epi64(round, round);
  57. qcoeff1 = _mm_adds_epi16(qcoeff1, round);
  58. qtmp0 = _mm_mulhi_epi16(qcoeff0, quant);
  59. quant = _mm_unpackhi_epi64(quant, quant);
  60. qtmp1 = _mm_mulhi_epi16(qcoeff1, quant);
  61. qtmp0 = _mm_add_epi16(qtmp0, qcoeff0);
  62. qtmp1 = _mm_add_epi16(qtmp1, qcoeff1);
  63. qcoeff0 = _mm_mulhi_epi16(qtmp0, shift);
  64. shift = _mm_unpackhi_epi64(shift, shift);
  65. qcoeff1 = _mm_mulhi_epi16(qtmp1, shift);
  66. // Reinsert signs
  67. qcoeff0 = _mm_xor_si128(qcoeff0, coeff0_sign);
  68. qcoeff1 = _mm_xor_si128(qcoeff1, coeff1_sign);
  69. qcoeff0 = _mm_sub_epi16(qcoeff0, coeff0_sign);
  70. qcoeff1 = _mm_sub_epi16(qcoeff1, coeff1_sign);
  71. // Mask out zbin threshold coeffs
  72. qcoeff0 = _mm_and_si128(qcoeff0, cmp_mask0);
  73. qcoeff1 = _mm_and_si128(qcoeff1, cmp_mask1);
  74. store_tran_low(qcoeff0, qcoeff_ptr);
  75. store_tran_low(qcoeff1, qcoeff_ptr + 8);
  76. coeff0 = _mm_mullo_epi16(qcoeff0, dequant);
  77. dequant = _mm_unpackhi_epi64(dequant, dequant);
  78. coeff1 = _mm_mullo_epi16(qcoeff1, dequant);
  79. store_tran_low(coeff0, dqcoeff_ptr);
  80. store_tran_low(coeff1, dqcoeff_ptr + 8);
  81. // Scan for eob.
  82. zero_coeff0 = _mm_cmpeq_epi16(coeff0, zero);
  83. zero_coeff1 = _mm_cmpeq_epi16(coeff1, zero);
  84. iscan0 = _mm_load_si128((const __m128i *)(iscan_ptr));
  85. iscan1 = _mm_load_si128((const __m128i *)(iscan_ptr + 8));
  86. // Add one to convert from indices to counts
  87. iscan0 = _mm_sub_epi16(iscan0, cmp_mask0);
  88. iscan1 = _mm_sub_epi16(iscan1, cmp_mask1);
  89. eob = _mm_andnot_si128(zero_coeff0, iscan0);
  90. eob1 = _mm_andnot_si128(zero_coeff1, iscan1);
  91. eob = _mm_max_epi16(eob, eob1);
  92. // AC only loop.
  93. while (index < n_coeffs) {
  94. coeff0 = load_tran_low(coeff_ptr + index);
  95. coeff1 = load_tran_low(coeff_ptr + index + 8);
  96. coeff0_sign = _mm_srai_epi16(coeff0, 15);
  97. coeff1_sign = _mm_srai_epi16(coeff1, 15);
  98. qcoeff0 = _mm_xor_si128(coeff0, coeff0_sign);
  99. qcoeff1 = _mm_xor_si128(coeff1, coeff1_sign);
  100. qcoeff0 = _mm_sub_epi16(qcoeff0, coeff0_sign);
  101. qcoeff1 = _mm_sub_epi16(qcoeff1, coeff1_sign);
  102. cmp_mask0 = _mm_cmpgt_epi16(qcoeff0, zbin);
  103. cmp_mask1 = _mm_cmpgt_epi16(qcoeff1, zbin);
  104. qcoeff0 = _mm_adds_epi16(qcoeff0, round);
  105. qcoeff1 = _mm_adds_epi16(qcoeff1, round);
  106. qtmp0 = _mm_mulhi_epi16(qcoeff0, quant);
  107. qtmp1 = _mm_mulhi_epi16(qcoeff1, quant);
  108. qtmp0 = _mm_add_epi16(qtmp0, qcoeff0);
  109. qtmp1 = _mm_add_epi16(qtmp1, qcoeff1);
  110. qcoeff0 = _mm_mulhi_epi16(qtmp0, shift);
  111. qcoeff1 = _mm_mulhi_epi16(qtmp1, shift);
  112. qcoeff0 = _mm_xor_si128(qcoeff0, coeff0_sign);
  113. qcoeff1 = _mm_xor_si128(qcoeff1, coeff1_sign);
  114. qcoeff0 = _mm_sub_epi16(qcoeff0, coeff0_sign);
  115. qcoeff1 = _mm_sub_epi16(qcoeff1, coeff1_sign);
  116. qcoeff0 = _mm_and_si128(qcoeff0, cmp_mask0);
  117. qcoeff1 = _mm_and_si128(qcoeff1, cmp_mask1);
  118. store_tran_low(qcoeff0, qcoeff_ptr + index);
  119. store_tran_low(qcoeff1, qcoeff_ptr + index + 8);
  120. coeff0 = _mm_mullo_epi16(qcoeff0, dequant);
  121. coeff1 = _mm_mullo_epi16(qcoeff1, dequant);
  122. store_tran_low(coeff0, dqcoeff_ptr + index);
  123. store_tran_low(coeff1, dqcoeff_ptr + index + 8);
  124. zero_coeff0 = _mm_cmpeq_epi16(coeff0, zero);
  125. zero_coeff1 = _mm_cmpeq_epi16(coeff1, zero);
  126. iscan0 = _mm_load_si128((const __m128i *)(iscan_ptr + index));
  127. iscan1 = _mm_load_si128((const __m128i *)(iscan_ptr + index + 8));
  128. iscan0 = _mm_sub_epi16(iscan0, cmp_mask0);
  129. iscan1 = _mm_sub_epi16(iscan1, cmp_mask1);
  130. eob0 = _mm_andnot_si128(zero_coeff0, iscan0);
  131. eob1 = _mm_andnot_si128(zero_coeff1, iscan1);
  132. eob0 = _mm_max_epi16(eob0, eob1);
  133. eob = _mm_max_epi16(eob, eob0);
  134. index += 16;
  135. }
  136. // Accumulate eob.
  137. {
  138. __m128i eob_shuffled;
  139. eob_shuffled = _mm_shuffle_epi32(eob, 0xe);
  140. eob = _mm_max_epi16(eob, eob_shuffled);
  141. eob_shuffled = _mm_shufflelo_epi16(eob, 0xe);
  142. eob = _mm_max_epi16(eob, eob_shuffled);
  143. eob_shuffled = _mm_shufflelo_epi16(eob, 0x1);
  144. eob = _mm_max_epi16(eob, eob_shuffled);
  145. *eob_ptr = _mm_extract_epi16(eob, 1);
  146. }
  147. }