• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
10 #ifndef WEBP_DSP_QUANT_H_
11 #define WEBP_DSP_QUANT_H_
12 
13 #include "src/dsp/dsp.h"
14 #include "src/webp/types.h"
15 
16 #if defined(WEBP_USE_NEON) && !defined(WEBP_ANDROID_NEON) && \
17     !defined(WEBP_HAVE_NEON_RTCD)
18 #include <arm_neon.h>
19 
20 #define IsFlat IsFlat_NEON
21 
horizontal_add_uint32x4(const uint32x4_t a)22 static uint32x2_t horizontal_add_uint32x4(const uint32x4_t a) {
23   const uint64x2_t b = vpaddlq_u32(a);
24   return vadd_u32(vreinterpret_u32_u64(vget_low_u64(b)),
25                   vreinterpret_u32_u64(vget_high_u64(b)));
26 }
27 
IsFlat(const int16_t * levels,int num_blocks,int thresh)28 static WEBP_INLINE int IsFlat(const int16_t* levels, int num_blocks,
29                               int thresh) {
30   const int16x8_t tst_ones = vdupq_n_s16(-1);
31   uint32x4_t sum = vdupq_n_u32(0);
32 
33   for (int i = 0; i < num_blocks; ++i) {
34     // Set DC to zero.
35     const int16x8_t a_0 = vsetq_lane_s16(0, vld1q_s16(levels), 0);
36     const int16x8_t a_1 = vld1q_s16(levels + 8);
37 
38     const uint16x8_t b_0 = vshrq_n_u16(vtstq_s16(a_0, tst_ones), 15);
39     const uint16x8_t b_1 = vshrq_n_u16(vtstq_s16(a_1, tst_ones), 15);
40 
41     sum = vpadalq_u16(sum, b_0);
42     sum = vpadalq_u16(sum, b_1);
43 
44     levels += 16;
45   }
46   return thresh >= (int32_t)vget_lane_u32(horizontal_add_uint32x4(sum), 0);
47 }
48 
49 #else
50 
51 #define IsFlat IsFlat_C
52 
IsFlat(const int16_t * levels,int num_blocks,int thresh)53 static WEBP_INLINE int IsFlat(const int16_t* levels, int num_blocks,
54                               int thresh) {
55   int score = 0;
56   while (num_blocks-- > 0) {      // TODO(skal): refine positional scoring?
57     int i;
58     for (i = 1; i < 16; ++i) {    // omit DC, we're only interested in AC
59       score += (levels[i] != 0);
60       if (score > thresh) return 0;
61     }
62     levels += 16;
63   }
64   return 1;
65 }
66 
67 #endif  // defined(WEBP_USE_NEON) && !defined(WEBP_ANDROID_NEON) &&
68         // !defined(WEBP_HAVE_NEON_RTCD)
69 
70 #endif  // WEBP_DSP_QUANT_H_
71