• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2021 The libgav1 Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "src/dsp/arm/common_neon.h"
16 
17 #include "gtest/gtest.h"
18 #include "src/utils/cpu.h"
19 
20 #if LIBGAV1_ENABLE_NEON
21 #include <cstdint>
22 
23 #include "tests/block_utils.h"
24 
25 namespace libgav1 {
26 namespace dsp {
27 namespace {
28 
29 constexpr int kMaxBlockWidth = 16;
30 constexpr int kMaxBlockHeight = 16;
31 
32 template <typename Pixel>
33 class TransposeTest : public testing::Test {
34  public:
TransposeTest()35   TransposeTest() {
36     for (int y = 0; y < kMaxBlockHeight; ++y) {
37       for (int x = 0; x < kMaxBlockWidth; ++x) {
38         src_block_[y][x] = y * 16 + x;
39         expected_transpose_[y][x] = x * 16 + y;
40       }
41     }
42   }
43 
44   TransposeTest(const TransposeTest&) = delete;
45   TransposeTest& operator=(const TransposeTest&) = delete;
46   ~TransposeTest() override = default;
47 
48  protected:
49   Pixel src_block_[kMaxBlockHeight][kMaxBlockWidth];
50   Pixel expected_transpose_[kMaxBlockHeight][kMaxBlockWidth];
51 };
52 
53 using TransposeTestLowBitdepth = TransposeTest<uint8_t>;
54 
TEST_F(TransposeTestLowBitdepth,Transpose4x4Test)55 TEST_F(TransposeTestLowBitdepth, Transpose4x4Test) {
56   uint8x8_t a = Load4<1>(src_block_[1], Load4(src_block_[0]));
57   uint8x8_t b = Load4<1>(src_block_[3], Load4(src_block_[2]));
58   Transpose4x4(&a, &b);
59   uint8_t output_4x4[4][4];
60   StoreLo4(output_4x4[0], a);
61   StoreLo4(output_4x4[1], b);
62   StoreHi4(output_4x4[2], a);
63   StoreHi4(output_4x4[3], b);
64   EXPECT_TRUE(test_utils::CompareBlocks(expected_transpose_[0], output_4x4[0],
65                                         4, 4, kMaxBlockWidth, 4, false));
66 }
67 
TEST_F(TransposeTestLowBitdepth,Transpose8x4Test)68 TEST_F(TransposeTestLowBitdepth, Transpose8x4Test) {
69   uint8x8_t a0 = Load4<1>(src_block_[4], Load4(src_block_[0]));
70   uint8x8_t a1 = Load4<1>(src_block_[5], Load4(src_block_[1]));
71   uint8x8_t a2 = Load4<1>(src_block_[6], Load4(src_block_[2]));
72   uint8x8_t a3 = Load4<1>(src_block_[7], Load4(src_block_[3]));
73   Transpose8x4(&a0, &a1, &a2, &a3);
74   uint8_t output_8x4[4][8];
75   vst1_u8(output_8x4[0], a0);
76   vst1_u8(output_8x4[1], a1);
77   vst1_u8(output_8x4[2], a2);
78   vst1_u8(output_8x4[3], a3);
79   EXPECT_TRUE(test_utils::CompareBlocks(expected_transpose_[0], output_8x4[0],
80                                         8, 4, kMaxBlockWidth, 8, false));
81 }
82 
TEST_F(TransposeTestLowBitdepth,Transpose8x8Test)83 TEST_F(TransposeTestLowBitdepth, Transpose8x8Test) {
84   uint8x8_t input_8x8[8];
85   for (int i = 0; i < 8; ++i) {
86     input_8x8[i] = vld1_u8(src_block_[i]);
87   }
88   Transpose8x8(input_8x8);
89   uint8_t output_8x8[8][8];
90   for (int i = 0; i < 8; ++i) {
91     vst1_u8(output_8x8[i], input_8x8[i]);
92   }
93   EXPECT_TRUE(test_utils::CompareBlocks(expected_transpose_[0], output_8x8[0],
94                                         8, 8, kMaxBlockWidth, 8, false));
95 }
96 
TEST_F(TransposeTestLowBitdepth,Transpose8x16Test)97 TEST_F(TransposeTestLowBitdepth, Transpose8x16Test) {
98   uint8x16_t input_8x16[8];
99   for (int i = 0; i < 8; ++i) {
100     input_8x16[i] =
101         vcombine_u8(vld1_u8(src_block_[i]), vld1_u8(src_block_[i + 8]));
102   }
103   Transpose8x16(input_8x16);
104   uint8_t output_16x8[8][16];
105   for (int i = 0; i < 8; ++i) {
106     vst1q_u8(output_16x8[i], input_8x16[i]);
107   }
108   EXPECT_TRUE(test_utils::CompareBlocks(expected_transpose_[0], output_16x8[0],
109                                         16, 8, kMaxBlockWidth, 16, false));
110 }
111 
112 using TransposeTestHighBitdepth = TransposeTest<uint16_t>;
113 
TEST_F(TransposeTestHighBitdepth,Transpose4x4Test)114 TEST_F(TransposeTestHighBitdepth, Transpose4x4Test) {
115   uint16x4_t input_4x4[4];
116   input_4x4[0] = vld1_u16(src_block_[0]);
117   input_4x4[1] = vld1_u16(src_block_[1]);
118   input_4x4[2] = vld1_u16(src_block_[2]);
119   input_4x4[3] = vld1_u16(src_block_[3]);
120   Transpose4x4(input_4x4);
121   uint16_t output_4x4[4][4];
122   for (int i = 0; i < 4; ++i) {
123     vst1_u16(output_4x4[i], input_4x4[i]);
124   }
125   EXPECT_TRUE(test_utils::CompareBlocks(expected_transpose_[0], output_4x4[0],
126                                         4, 4, kMaxBlockWidth, 4, false));
127 }
128 
TEST_F(TransposeTestHighBitdepth,Transpose4x8Test)129 TEST_F(TransposeTestHighBitdepth, Transpose4x8Test) {
130   uint16x8_t input_4x8[4];
131   for (int i = 0; i < 4; ++i) {
132     input_4x8[i] = vld1q_u16(src_block_[i]);
133   }
134   Transpose4x8(input_4x8);
135   uint16_t output_4x8[4][8];
136   for (int i = 0; i < 4; ++i) {
137     vst1q_u16(output_4x8[i], input_4x8[i]);
138     memcpy(&expected_transpose_[i][4], &expected_transpose_[i + 4][0],
139            4 * sizeof(expected_transpose_[0][0]));
140   }
141   EXPECT_TRUE(test_utils::CompareBlocks(expected_transpose_[0], output_4x8[0],
142                                         8, 4, kMaxBlockWidth, 8, false));
143 }
144 
TEST_F(TransposeTestHighBitdepth,LoopFilterTranspose4x8Test)145 TEST_F(TransposeTestHighBitdepth, LoopFilterTranspose4x8Test) {
146   uint16x8_t input_4x8[4];
147   for (int i = 0; i < 4; ++i) {
148     input_4x8[i] = vld1q_u16(src_block_[i]);
149   }
150   LoopFilterTranspose4x8(input_4x8);
151   uint16_t output_4x8[4][8];
152   for (int i = 0; i < 4; ++i) {
153     vst1q_u16(output_4x8[i], input_4x8[i]);
154   }
155   // a[0]: 03 13 23 33 04 14 24 34  p0q0
156   // a[1]: 02 12 22 32 05 15 25 35  p1q1
157   // a[2]: 01 11 21 31 06 16 26 36  p2q2
158   // a[3]: 00 10 20 30 07 17 27 37  p3q3
159   static constexpr uint16_t expected_output[4][8] = {
160       {0x03, 0x13, 0x23, 0x33, 0x04, 0x14, 0x24, 0x34},
161       {0x02, 0x12, 0x22, 0x32, 0x05, 0x15, 0x25, 0x35},
162       {0x01, 0x11, 0x21, 0x31, 0x06, 0x16, 0x26, 0x36},
163       {0x00, 0x10, 0x20, 0x30, 0x07, 0x17, 0x27, 0x37},
164   };
165   EXPECT_TRUE(test_utils::CompareBlocks(expected_output[0], output_4x8[0], 8, 4,
166                                         8, 8, false));
167 }
168 
TEST_F(TransposeTestHighBitdepth,Transpose8x8Test)169 TEST_F(TransposeTestHighBitdepth, Transpose8x8Test) {
170   uint16x8_t input_8x8[8];
171   for (int i = 0; i < 8; ++i) {
172     input_8x8[i] = vld1q_u16(src_block_[i]);
173   }
174   Transpose8x8(input_8x8);
175   uint16_t output_8x8[8][8];
176   for (int i = 0; i < 8; ++i) {
177     vst1q_u16(output_8x8[i], input_8x8[i]);
178   }
179   EXPECT_TRUE(test_utils::CompareBlocks(expected_transpose_[0], output_8x8[0],
180                                         8, 8, kMaxBlockWidth, 8, false));
181 }
182 
TEST_F(TransposeTestHighBitdepth,Transpose8x8SignedTest)183 TEST_F(TransposeTestHighBitdepth, Transpose8x8SignedTest) {
184   int16x8_t input_8x8[8];
185   for (int i = 0; i < 8; ++i) {
186     input_8x8[i] = vreinterpretq_s16_u16(vld1q_u16(src_block_[i]));
187   }
188   Transpose8x8(input_8x8);
189   uint16_t output_8x8[8][8];
190   for (int i = 0; i < 8; ++i) {
191     vst1q_u16(output_8x8[i], vreinterpretq_u16_s16(input_8x8[i]));
192   }
193   EXPECT_TRUE(test_utils::CompareBlocks(expected_transpose_[0], output_8x8[0],
194                                         8, 8, kMaxBlockWidth, 8, false));
195 }
196 
197 }  // namespace
198 }  // namespace dsp
199 }  // namespace libgav1
200 
201 #else  // !LIBGAV1_ENABLE_NEON
202 
TEST(CommonDspTest,NEON)203 TEST(CommonDspTest, NEON) {
204   GTEST_SKIP()
205       << "Build this module for Arm with NEON enabled to enable the tests.";
206 }
207 
208 #endif  // LIBGAV1_ENABLE_NEON
209