quant.h 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. // Copyright 2018 Google Inc. All Rights Reserved.
  2. //
  3. // Use of this source code is governed by a BSD-style license
  4. // that can be found in the COPYING file in the root of the source
  5. // tree. An additional intellectual property rights grant can be found
  6. // in the file PATENTS. All contributing project authors may
  7. // be found in the AUTHORS file in the root of the source tree.
  8. // -----------------------------------------------------------------------------
  9. #ifndef WEBP_DSP_QUANT_H_
  10. #define WEBP_DSP_QUANT_H_
  11. #include <string.h>
  12. #include "./dsp.h"
  13. #include "../webp/types.h"
  14. #if defined(WEBP_USE_NEON) && !defined(WEBP_ANDROID_NEON) && \
  15. !defined(WEBP_HAVE_NEON_RTCD)
  16. #include <arm_neon.h>
  17. #define IsFlat IsFlat_NEON
  18. static uint32x2_t horizontal_add_uint32x4(const uint32x4_t a) {
  19. const uint64x2_t b = vpaddlq_u32(a);
  20. return vadd_u32(vreinterpret_u32_u64(vget_low_u64(b)),
  21. vreinterpret_u32_u64(vget_high_u64(b)));
  22. }
  23. static WEBP_INLINE int IsFlat(const int16_t* levels, int num_blocks,
  24. int thresh) {
  25. const int16x8_t tst_ones = vdupq_n_s16(-1);
  26. uint32x4_t sum = vdupq_n_u32(0);
  27. for (int i = 0; i < num_blocks; ++i) {
  28. // Set DC to zero.
  29. const int16x8_t a_0 = vsetq_lane_s16(0, vld1q_s16(levels), 0);
  30. const int16x8_t a_1 = vld1q_s16(levels + 8);
  31. const uint16x8_t b_0 = vshrq_n_u16(vtstq_s16(a_0, tst_ones), 15);
  32. const uint16x8_t b_1 = vshrq_n_u16(vtstq_s16(a_1, tst_ones), 15);
  33. sum = vpadalq_u16(sum, b_0);
  34. sum = vpadalq_u16(sum, b_1);
  35. levels += 16;
  36. }
  37. return thresh >= (int32_t)vget_lane_u32(horizontal_add_uint32x4(sum), 0);
  38. }
  39. #else
  40. #define IsFlat IsFlat_C
  41. static WEBP_INLINE int IsFlat(const int16_t* levels, int num_blocks,
  42. int thresh) {
  43. int score = 0;
  44. while (num_blocks-- > 0) { // TODO(skal): refine positional scoring?
  45. int i;
  46. for (i = 1; i < 16; ++i) { // omit DC, we're only interested in AC
  47. score += (levels[i] != 0);
  48. if (score > thresh) return 0;
  49. }
  50. levels += 16;
  51. }
  52. return 1;
  53. }
  54. #endif // defined(WEBP_USE_NEON) && !defined(WEBP_ANDROID_NEON) &&
  55. // !defined(WEBP_HAVE_NEON_RTCD)
  56. static WEBP_INLINE int IsFlatSource16(const uint8_t* src) {
  57. const uint32_t v = src[0] * 0x01010101u;
  58. int i;
  59. for (i = 0; i < 16; ++i) {
  60. if (memcmp(src + 0, &v, 4) || memcmp(src + 4, &v, 4) ||
  61. memcmp(src + 8, &v, 4) || memcmp(src + 12, &v, 4)) {
  62. return 0;
  63. }
  64. src += BPS;
  65. }
  66. return 1;
  67. }
  68. #endif // WEBP_DSP_QUANT_H_