xref: /aosp_15_r20/external/libvpx/test/pp_filter_test.cc (revision fb1b10ab9aebc7c7068eedab379b749d7e3900be)
1 /*
2  *  Copyright (c) 2012 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 
11 #include <limits.h>
12 
13 #include <memory>
14 
15 #include "./vpx_config.h"
16 #include "./vpx_dsp_rtcd.h"
17 #include "gtest/gtest.h"
18 #include "test/acm_random.h"
19 #include "test/bench.h"
20 #include "test/buffer.h"
21 #include "test/clear_system_state.h"
22 #include "test/register_state_check.h"
23 #include "vpx/vpx_integer.h"
24 #include "vpx_mem/vpx_mem.h"
25 
26 using libvpx_test::ACMRandom;
27 using libvpx_test::Buffer;
28 
29 typedef void (*VpxPostProcDownAndAcrossMbRowFunc)(
30     unsigned char *src_ptr, unsigned char *dst_ptr, int src_pixels_per_line,
31     int dst_pixels_per_line, int cols, unsigned char *flimit, int size);
32 
33 typedef void (*VpxMbPostProcAcrossIpFunc)(unsigned char *src, int pitch,
34                                           int rows, int cols, int flimit);
35 
36 typedef void (*VpxMbPostProcDownFunc)(unsigned char *dst, int pitch, int rows,
37                                       int cols, int flimit);
38 
39 namespace {
40 // Compute the filter level used in post proc from the loop filter strength
q2mbl(int x)41 int q2mbl(int x) {
42   if (x < 20) x = 20;
43 
44   x = 50 + (x - 50) * 10 / 8;
45   return x * x / 3;
46 }
47 
48 class VpxPostProcDownAndAcrossMbRowTest
49     : public AbstractBench,
50       public ::testing::TestWithParam<VpxPostProcDownAndAcrossMbRowFunc> {
51  public:
VpxPostProcDownAndAcrossMbRowTest()52   VpxPostProcDownAndAcrossMbRowTest()
53       : mb_post_proc_down_and_across_(GetParam()) {}
TearDown()54   void TearDown() override { libvpx_test::ClearSystemState(); }
55 
56  protected:
57   void Run() override;
58 
59   const VpxPostProcDownAndAcrossMbRowFunc mb_post_proc_down_and_across_;
60   // Size of the underlying data block that will be filtered.
61   int block_width_;
62   int block_height_;
63   Buffer<uint8_t> *src_image_;
64   Buffer<uint8_t> *dst_image_;
65   uint8_t *flimits_;
66 };
67 
Run()68 void VpxPostProcDownAndAcrossMbRowTest::Run() {
69   mb_post_proc_down_and_across_(
70       src_image_->TopLeftPixel(), dst_image_->TopLeftPixel(),
71       src_image_->stride(), dst_image_->stride(), block_width_, flimits_, 16);
72 }
73 
74 // Test routine for the VPx post-processing function
75 // vpx_post_proc_down_and_across_mb_row_c.
76 
TEST_P(VpxPostProcDownAndAcrossMbRowTest,CheckFilterOutput)77 TEST_P(VpxPostProcDownAndAcrossMbRowTest, CheckFilterOutput) {
78   // Size of the underlying data block that will be filtered.
79   block_width_ = 16;
80   block_height_ = 16;
81 
82   // 5-tap filter needs 2 padding rows above and below the block in the input.
83   Buffer<uint8_t> src_image = Buffer<uint8_t>(block_width_, block_height_, 2);
84   ASSERT_TRUE(src_image.Init());
85 
86   // Filter extends output block by 8 samples at left and right edges.
87   // Though the left padding is only 8 bytes, the assembly code tries to
88   // read 16 bytes before the pointer.
89   Buffer<uint8_t> dst_image =
90       Buffer<uint8_t>(block_width_, block_height_, 8, 16, 8, 8);
91   ASSERT_TRUE(dst_image.Init());
92 
93   flimits_ = reinterpret_cast<uint8_t *>(vpx_memalign(16, block_width_));
94   (void)memset(flimits_, 255, block_width_);
95 
96   // Initialize pixels in the input:
97   //   block pixels to value 1,
98   //   border pixels to value 10.
99   src_image.SetPadding(10);
100   src_image.Set(1);
101 
102   // Initialize pixels in the output to 99.
103   dst_image.Set(99);
104 
105   ASM_REGISTER_STATE_CHECK(mb_post_proc_down_and_across_(
106       src_image.TopLeftPixel(), dst_image.TopLeftPixel(), src_image.stride(),
107       dst_image.stride(), block_width_, flimits_, 16));
108 
109   static const uint8_t kExpectedOutput[] = { 4, 3, 1, 1, 1, 1, 1, 1,
110                                              1, 1, 1, 1, 1, 1, 3, 4 };
111 
112   uint8_t *pixel_ptr = dst_image.TopLeftPixel();
113   for (int i = 0; i < block_height_; ++i) {
114     for (int j = 0; j < block_width_; ++j) {
115       ASSERT_EQ(kExpectedOutput[i], pixel_ptr[j])
116           << "at (" << i << ", " << j << ")";
117     }
118     pixel_ptr += dst_image.stride();
119   }
120 
121   vpx_free(flimits_);
122 }
123 
TEST_P(VpxPostProcDownAndAcrossMbRowTest,CheckCvsAssembly)124 TEST_P(VpxPostProcDownAndAcrossMbRowTest, CheckCvsAssembly) {
125   // Size of the underlying data block that will be filtered.
126   // Y blocks are always a multiple of 16 wide and exactly 16 high. U and V
127   // blocks are always a multiple of 8 wide and exactly 8 high.
128   block_width_ = 136;
129   block_height_ = 16;
130 
131   // 5-tap filter needs 2 padding rows above and below the block in the input.
132   // SSE2 reads in blocks of 16. Pad an extra 8 in case the width is not %16.
133   Buffer<uint8_t> src_image =
134       Buffer<uint8_t>(block_width_, block_height_, 2, 2, 10, 2);
135   ASSERT_TRUE(src_image.Init());
136 
137   // Filter extends output block by 8 samples at left and right edges.
138   // Though the left padding is only 8 bytes, there is 'above' padding as well
139   // so when the assembly code tries to read 16 bytes before the pointer it is
140   // not a problem.
141   // SSE2 reads in blocks of 16. Pad an extra 8 in case the width is not %16.
142   Buffer<uint8_t> dst_image =
143       Buffer<uint8_t>(block_width_, block_height_, 8, 8, 16, 8);
144   ASSERT_TRUE(dst_image.Init());
145   Buffer<uint8_t> dst_image_ref =
146       Buffer<uint8_t>(block_width_, block_height_, 8);
147   ASSERT_TRUE(dst_image_ref.Init());
148 
149   // Filter values are set in blocks of 16 for Y and 8 for U/V. Each macroblock
150   // can have a different filter. SSE2 assembly reads flimits in blocks of 16 so
151   // it must be padded out.
152   const int flimits_width = block_width_ % 16 ? block_width_ + 8 : block_width_;
153   flimits_ = reinterpret_cast<uint8_t *>(vpx_memalign(16, flimits_width));
154 
155   ACMRandom rnd;
156   rnd.Reset(ACMRandom::DeterministicSeed());
157   // Initialize pixels in the input:
158   //   block pixels to random values.
159   //   border pixels to value 10.
160   src_image.SetPadding(10);
161   src_image.Set(&rnd, &ACMRandom::Rand8);
162 
163   for (int blocks = 0; blocks < block_width_; blocks += 8) {
164     (void)memset(flimits_, 0, sizeof(*flimits_) * flimits_width);
165 
166     for (int f = 0; f < 255; f++) {
167       (void)memset(flimits_ + blocks, f, sizeof(*flimits_) * 8);
168       dst_image.Set(0);
169       dst_image_ref.Set(0);
170 
171       vpx_post_proc_down_and_across_mb_row_c(
172           src_image.TopLeftPixel(), dst_image_ref.TopLeftPixel(),
173           src_image.stride(), dst_image_ref.stride(), block_width_, flimits_,
174           block_height_);
175       ASM_REGISTER_STATE_CHECK(mb_post_proc_down_and_across_(
176           src_image.TopLeftPixel(), dst_image.TopLeftPixel(),
177           src_image.stride(), dst_image.stride(), block_width_, flimits_,
178           block_height_));
179 
180       ASSERT_TRUE(dst_image.CheckValues(dst_image_ref));
181     }
182   }
183 
184   vpx_free(flimits_);
185 }
186 
TEST_P(VpxPostProcDownAndAcrossMbRowTest,DISABLED_Speed)187 TEST_P(VpxPostProcDownAndAcrossMbRowTest, DISABLED_Speed) {
188   // Size of the underlying data block that will be filtered.
189   block_width_ = 16;
190   block_height_ = 16;
191 
192   // 5-tap filter needs 2 padding rows above and below the block in the input.
193   Buffer<uint8_t> src_image = Buffer<uint8_t>(block_width_, block_height_, 2);
194   ASSERT_TRUE(src_image.Init());
195   this->src_image_ = &src_image;
196 
197   // Filter extends output block by 8 samples at left and right edges.
198   // Though the left padding is only 8 bytes, the assembly code tries to
199   // read 16 bytes before the pointer.
200   Buffer<uint8_t> dst_image =
201       Buffer<uint8_t>(block_width_, block_height_, 8, 16, 8, 8);
202   ASSERT_TRUE(dst_image.Init());
203   this->dst_image_ = &dst_image;
204 
205   flimits_ = reinterpret_cast<uint8_t *>(vpx_memalign(16, block_width_));
206   (void)memset(flimits_, 255, block_width_);
207 
208   // Initialize pixels in the input:
209   //   block pixels to value 1,
210   //   border pixels to value 10.
211   src_image.SetPadding(10);
212   src_image.Set(1);
213 
214   // Initialize pixels in the output to 99.
215   dst_image.Set(99);
216 
217   RunNTimes(INT16_MAX);
218   PrintMedian("16x16");
219 
220   vpx_free(flimits_);
221 }
222 
223 class VpxMbPostProcAcrossIpTest
224     : public AbstractBench,
225       public ::testing::TestWithParam<VpxMbPostProcAcrossIpFunc> {
226  public:
VpxMbPostProcAcrossIpTest()227   VpxMbPostProcAcrossIpTest()
228       : rows_(16), cols_(16), mb_post_proc_across_ip_(GetParam()),
229         src_(Buffer<uint8_t>(rows_, cols_, 8, 8, 17, 8)) {}
TearDown()230   void TearDown() override { libvpx_test::ClearSystemState(); }
231 
232  protected:
233   void Run() override;
234 
SetCols(unsigned char * s,int rows,int cols,int src_width)235   void SetCols(unsigned char *s, int rows, int cols, int src_width) {
236     for (int r = 0; r < rows; r++) {
237       for (int c = 0; c < cols; c++) {
238         s[c] = c;
239       }
240       s += src_width;
241     }
242   }
243 
RunComparison(const unsigned char * expected_output,unsigned char * src_c,int rows,int cols,int src_pitch)244   void RunComparison(const unsigned char *expected_output, unsigned char *src_c,
245                      int rows, int cols, int src_pitch) {
246     for (int r = 0; r < rows; r++) {
247       for (int c = 0; c < cols; c++) {
248         ASSERT_EQ(expected_output[c], src_c[c])
249             << "at (" << r << ", " << c << ")";
250       }
251       src_c += src_pitch;
252     }
253   }
254 
RunFilterLevel(unsigned char * s,int rows,int cols,int src_width,int filter_level,const unsigned char * expected_output)255   void RunFilterLevel(unsigned char *s, int rows, int cols, int src_width,
256                       int filter_level, const unsigned char *expected_output) {
257     ASM_REGISTER_STATE_CHECK(
258         GetParam()(s, src_width, rows, cols, filter_level));
259     RunComparison(expected_output, s, rows, cols, src_width);
260   }
261 
262   const int rows_;
263   const int cols_;
264   const VpxMbPostProcAcrossIpFunc mb_post_proc_across_ip_;
265   Buffer<uint8_t> src_;
266 };
267 
Run()268 void VpxMbPostProcAcrossIpTest::Run() {
269   mb_post_proc_across_ip_(src_.TopLeftPixel(), src_.stride(), rows_, cols_,
270                           q2mbl(0));
271 }
272 
TEST_P(VpxMbPostProcAcrossIpTest,CheckLowFilterOutput)273 TEST_P(VpxMbPostProcAcrossIpTest, CheckLowFilterOutput) {
274   ASSERT_TRUE(src_.Init());
275   src_.SetPadding(10);
276   SetCols(src_.TopLeftPixel(), rows_, cols_, src_.stride());
277 
278   Buffer<uint8_t> expected_output = Buffer<uint8_t>(cols_, rows_, 0);
279   ASSERT_TRUE(expected_output.Init());
280   SetCols(expected_output.TopLeftPixel(), rows_, cols_,
281           expected_output.stride());
282 
283   RunFilterLevel(src_.TopLeftPixel(), rows_, cols_, src_.stride(), q2mbl(0),
284                  expected_output.TopLeftPixel());
285 }
286 
TEST_P(VpxMbPostProcAcrossIpTest,CheckMediumFilterOutput)287 TEST_P(VpxMbPostProcAcrossIpTest, CheckMediumFilterOutput) {
288   ASSERT_TRUE(src_.Init());
289   src_.SetPadding(10);
290   SetCols(src_.TopLeftPixel(), rows_, cols_, src_.stride());
291 
292   static const unsigned char kExpectedOutput[] = {
293     2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 13
294   };
295 
296   RunFilterLevel(src_.TopLeftPixel(), rows_, cols_, src_.stride(), q2mbl(70),
297                  kExpectedOutput);
298 }
299 
TEST_P(VpxMbPostProcAcrossIpTest,CheckHighFilterOutput)300 TEST_P(VpxMbPostProcAcrossIpTest, CheckHighFilterOutput) {
301   ASSERT_TRUE(src_.Init());
302   src_.SetPadding(10);
303   SetCols(src_.TopLeftPixel(), rows_, cols_, src_.stride());
304 
305   static const unsigned char kExpectedOutput[] = {
306     2, 2, 3, 4, 4, 5, 6, 7, 8, 9, 10, 11, 11, 12, 13, 13
307   };
308 
309   RunFilterLevel(src_.TopLeftPixel(), rows_, cols_, src_.stride(), INT_MAX,
310                  kExpectedOutput);
311 
312   SetCols(src_.TopLeftPixel(), rows_, cols_, src_.stride());
313 
314   RunFilterLevel(src_.TopLeftPixel(), rows_, cols_, src_.stride(), q2mbl(100),
315                  kExpectedOutput);
316 }
317 
TEST_P(VpxMbPostProcAcrossIpTest,CheckCvsAssembly)318 TEST_P(VpxMbPostProcAcrossIpTest, CheckCvsAssembly) {
319   Buffer<uint8_t> c_mem = Buffer<uint8_t>(cols_, rows_, 8, 8, 17, 8);
320   ASSERT_TRUE(c_mem.Init());
321   Buffer<uint8_t> asm_mem = Buffer<uint8_t>(cols_, rows_, 8, 8, 17, 8);
322   ASSERT_TRUE(asm_mem.Init());
323 
324   // When level >= 100, the filter behaves the same as the level = INT_MAX
325   // When level < 20, it behaves the same as the level = 0
326   for (int level = 0; level < 100; level++) {
327     c_mem.SetPadding(10);
328     asm_mem.SetPadding(10);
329     SetCols(c_mem.TopLeftPixel(), rows_, cols_, c_mem.stride());
330     SetCols(asm_mem.TopLeftPixel(), rows_, cols_, asm_mem.stride());
331 
332     vpx_mbpost_proc_across_ip_c(c_mem.TopLeftPixel(), c_mem.stride(), rows_,
333                                 cols_, q2mbl(level));
334     ASM_REGISTER_STATE_CHECK(GetParam()(
335         asm_mem.TopLeftPixel(), asm_mem.stride(), rows_, cols_, q2mbl(level)));
336 
337     ASSERT_TRUE(asm_mem.CheckValues(c_mem));
338   }
339 }
340 
TEST_P(VpxMbPostProcAcrossIpTest,DISABLED_Speed)341 TEST_P(VpxMbPostProcAcrossIpTest, DISABLED_Speed) {
342   ASSERT_TRUE(src_.Init());
343   src_.SetPadding(10);
344 
345   SetCols(src_.TopLeftPixel(), rows_, cols_, src_.stride());
346 
347   RunNTimes(100000);
348   PrintMedian("16x16");
349 }
350 
351 class VpxMbPostProcDownTest
352     : public AbstractBench,
353       public ::testing::TestWithParam<VpxMbPostProcDownFunc> {
354  public:
VpxMbPostProcDownTest()355   VpxMbPostProcDownTest()
356       : rows_(16), cols_(16), mb_post_proc_down_(GetParam()),
357         src_c_(Buffer<uint8_t>(rows_, cols_, 8, 8, 8, 17)) {}
358 
TearDown()359   void TearDown() override { libvpx_test::ClearSystemState(); }
360 
361  protected:
362   void Run() override;
363 
SetRows(unsigned char * src_c,int rows,int cols,int src_width)364   void SetRows(unsigned char *src_c, int rows, int cols, int src_width) {
365     for (int r = 0; r < rows; r++) {
366       memset(src_c, r, cols);
367       src_c += src_width;
368     }
369   }
370 
RunComparison(const unsigned char * expected_output,unsigned char * src_c,int rows,int cols,int src_pitch)371   void RunComparison(const unsigned char *expected_output, unsigned char *src_c,
372                      int rows, int cols, int src_pitch) {
373     for (int r = 0; r < rows; r++) {
374       for (int c = 0; c < cols; c++) {
375         ASSERT_EQ(expected_output[r * rows + c], src_c[c])
376             << "at (" << r << ", " << c << ")";
377       }
378       src_c += src_pitch;
379     }
380   }
381 
RunFilterLevel(unsigned char * s,int rows,int cols,int src_width,int filter_level,const unsigned char * expected_output)382   void RunFilterLevel(unsigned char *s, int rows, int cols, int src_width,
383                       int filter_level, const unsigned char *expected_output) {
384     ASM_REGISTER_STATE_CHECK(
385         mb_post_proc_down_(s, src_width, rows, cols, filter_level));
386     RunComparison(expected_output, s, rows, cols, src_width);
387   }
388 
389   const int rows_;
390   const int cols_;
391   const VpxMbPostProcDownFunc mb_post_proc_down_;
392   Buffer<uint8_t> src_c_;
393 };
394 
Run()395 void VpxMbPostProcDownTest::Run() {
396   mb_post_proc_down_(src_c_.TopLeftPixel(), src_c_.stride(), rows_, cols_,
397                      q2mbl(0));
398 }
399 
TEST_P(VpxMbPostProcDownTest,CheckHighFilterOutput)400 TEST_P(VpxMbPostProcDownTest, CheckHighFilterOutput) {
401   ASSERT_TRUE(src_c_.Init());
402   src_c_.SetPadding(10);
403 
404   SetRows(src_c_.TopLeftPixel(), rows_, cols_, src_c_.stride());
405 
406   static const unsigned char kExpectedOutput[] = {
407     2,  2,  1,  1,  2,  2,  2,  2,  2,  2,  1,  1,  2,  2,  2,  2,  2,  2,  2,
408     2,  3,  2,  2,  2,  2,  2,  2,  2,  3,  2,  2,  2,  3,  3,  3,  3,  3,  3,
409     3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  4,  4,  3,  4,  4,  3,  3,  3,
410     4,  4,  3,  4,  4,  3,  3,  4,  5,  4,  4,  4,  4,  4,  4,  4,  5,  4,  4,
411     4,  4,  4,  4,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,
412     5,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  7,  7,
413     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  8,  8,  8,  8,  8,
414     8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  9,  8,  9,  9,  8,  8,  8,  9,
415     9,  8,  9,  9,  8,  8,  8,  9,  9,  10, 10, 9,  9,  9,  10, 10, 9,  10, 10,
416     9,  9,  9,  10, 10, 10, 11, 10, 10, 10, 11, 10, 11, 10, 11, 10, 10, 10, 11,
417     10, 11, 11, 11, 11, 11, 11, 11, 12, 11, 11, 11, 11, 11, 11, 11, 12, 11, 12,
418     12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 12,
419     13, 12, 13, 12, 12, 12, 13, 12, 13, 12, 13, 12, 13, 13, 13, 14, 13, 13, 13,
420     13, 13, 13, 13, 14, 13, 13, 13, 13
421   };
422 
423   RunFilterLevel(src_c_.TopLeftPixel(), rows_, cols_, src_c_.stride(), INT_MAX,
424                  kExpectedOutput);
425 
426   src_c_.SetPadding(10);
427   SetRows(src_c_.TopLeftPixel(), rows_, cols_, src_c_.stride());
428   RunFilterLevel(src_c_.TopLeftPixel(), rows_, cols_, src_c_.stride(),
429                  q2mbl(100), kExpectedOutput);
430 }
431 
TEST_P(VpxMbPostProcDownTest,CheckMediumFilterOutput)432 TEST_P(VpxMbPostProcDownTest, CheckMediumFilterOutput) {
433   ASSERT_TRUE(src_c_.Init());
434   src_c_.SetPadding(10);
435 
436   SetRows(src_c_.TopLeftPixel(), rows_, cols_, src_c_.stride());
437 
438   static const unsigned char kExpectedOutput[] = {
439     2,  2,  1,  1,  2,  2,  2,  2,  2,  2,  1,  1,  2,  2,  2,  2,  2,  2,  2,
440     2,  3,  2,  2,  2,  2,  2,  2,  2,  3,  2,  2,  2,  2,  2,  2,  2,  2,  2,
441     2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  3,  3,  3,  3,  3,  3,  3,  3,  3,
442     3,  3,  3,  3,  3,  3,  3,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,
443     4,  4,  4,  4,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,
444     5,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  7,  7,
445     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  8,  8,  8,  8,  8,
446     8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  9,  9,  9,  9,  9,  9,  9,  9,
447     9,  9,  9,  9,  9,  9,  9,  9,  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
448     10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
449     11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13,
450     13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, 12, 13, 12,
451     13, 12, 13, 12, 12, 12, 13, 12, 13, 12, 13, 12, 13, 13, 13, 14, 13, 13, 13,
452     13, 13, 13, 13, 14, 13, 13, 13, 13
453   };
454 
455   RunFilterLevel(src_c_.TopLeftPixel(), rows_, cols_, src_c_.stride(),
456                  q2mbl(70), kExpectedOutput);
457 }
458 
TEST_P(VpxMbPostProcDownTest,CheckLowFilterOutput)459 TEST_P(VpxMbPostProcDownTest, CheckLowFilterOutput) {
460   ASSERT_TRUE(src_c_.Init());
461   src_c_.SetPadding(10);
462 
463   SetRows(src_c_.TopLeftPixel(), rows_, cols_, src_c_.stride());
464 
465   std::unique_ptr<unsigned char[]> expected_output(
466       new unsigned char[rows_ * cols_]);
467   ASSERT_NE(expected_output, nullptr);
468   SetRows(expected_output.get(), rows_, cols_, cols_);
469 
470   RunFilterLevel(src_c_.TopLeftPixel(), rows_, cols_, src_c_.stride(), q2mbl(0),
471                  expected_output.get());
472 }
473 
TEST_P(VpxMbPostProcDownTest,CheckCvsAssembly)474 TEST_P(VpxMbPostProcDownTest, CheckCvsAssembly) {
475   ACMRandom rnd;
476   rnd.Reset(ACMRandom::DeterministicSeed());
477 
478   ASSERT_TRUE(src_c_.Init());
479   Buffer<uint8_t> src_asm = Buffer<uint8_t>(cols_, rows_, 8, 8, 8, 17);
480   ASSERT_TRUE(src_asm.Init());
481 
482   for (int level = 0; level < 100; level++) {
483     src_c_.SetPadding(10);
484     src_asm.SetPadding(10);
485     src_c_.Set(&rnd, &ACMRandom::Rand8);
486     src_asm.CopyFrom(src_c_);
487 
488     vpx_mbpost_proc_down_c(src_c_.TopLeftPixel(), src_c_.stride(), rows_, cols_,
489                            q2mbl(level));
490     ASM_REGISTER_STATE_CHECK(mb_post_proc_down_(
491         src_asm.TopLeftPixel(), src_asm.stride(), rows_, cols_, q2mbl(level)));
492     ASSERT_TRUE(src_asm.CheckValues(src_c_));
493 
494     src_c_.SetPadding(10);
495     src_asm.SetPadding(10);
496     src_c_.Set(&rnd, &ACMRandom::Rand8Extremes);
497     src_asm.CopyFrom(src_c_);
498 
499     vpx_mbpost_proc_down_c(src_c_.TopLeftPixel(), src_c_.stride(), rows_, cols_,
500                            q2mbl(level));
501     ASM_REGISTER_STATE_CHECK(mb_post_proc_down_(
502         src_asm.TopLeftPixel(), src_asm.stride(), rows_, cols_, q2mbl(level)));
503     ASSERT_TRUE(src_asm.CheckValues(src_c_));
504   }
505 }
506 
TEST_P(VpxMbPostProcDownTest,DISABLED_Speed)507 TEST_P(VpxMbPostProcDownTest, DISABLED_Speed) {
508   ASSERT_TRUE(src_c_.Init());
509   src_c_.SetPadding(10);
510 
511   SetRows(src_c_.TopLeftPixel(), rows_, cols_, src_c_.stride());
512 
513   RunNTimes(100000);
514   PrintMedian("16x16");
515 }
516 
517 INSTANTIATE_TEST_SUITE_P(
518     C, VpxPostProcDownAndAcrossMbRowTest,
519     ::testing::Values(vpx_post_proc_down_and_across_mb_row_c));
520 
521 INSTANTIATE_TEST_SUITE_P(C, VpxMbPostProcAcrossIpTest,
522                          ::testing::Values(vpx_mbpost_proc_across_ip_c));
523 
524 INSTANTIATE_TEST_SUITE_P(C, VpxMbPostProcDownTest,
525                          ::testing::Values(vpx_mbpost_proc_down_c));
526 
527 #if HAVE_SSE2
528 INSTANTIATE_TEST_SUITE_P(
529     SSE2, VpxPostProcDownAndAcrossMbRowTest,
530     ::testing::Values(vpx_post_proc_down_and_across_mb_row_sse2));
531 
532 INSTANTIATE_TEST_SUITE_P(SSE2, VpxMbPostProcAcrossIpTest,
533                          ::testing::Values(vpx_mbpost_proc_across_ip_sse2));
534 
535 INSTANTIATE_TEST_SUITE_P(SSE2, VpxMbPostProcDownTest,
536                          ::testing::Values(vpx_mbpost_proc_down_sse2));
537 #endif  // HAVE_SSE2
538 
539 #if HAVE_NEON
540 INSTANTIATE_TEST_SUITE_P(
541     NEON, VpxPostProcDownAndAcrossMbRowTest,
542     ::testing::Values(vpx_post_proc_down_and_across_mb_row_neon));
543 
544 INSTANTIATE_TEST_SUITE_P(NEON, VpxMbPostProcAcrossIpTest,
545                          ::testing::Values(vpx_mbpost_proc_across_ip_neon));
546 
547 INSTANTIATE_TEST_SUITE_P(NEON, VpxMbPostProcDownTest,
548                          ::testing::Values(vpx_mbpost_proc_down_neon));
549 #endif  // HAVE_NEON
550 
551 #if HAVE_MSA
552 INSTANTIATE_TEST_SUITE_P(
553     MSA, VpxPostProcDownAndAcrossMbRowTest,
554     ::testing::Values(vpx_post_proc_down_and_across_mb_row_msa));
555 
556 INSTANTIATE_TEST_SUITE_P(MSA, VpxMbPostProcAcrossIpTest,
557                          ::testing::Values(vpx_mbpost_proc_across_ip_msa));
558 
559 INSTANTIATE_TEST_SUITE_P(MSA, VpxMbPostProcDownTest,
560                          ::testing::Values(vpx_mbpost_proc_down_msa));
561 #endif  // HAVE_MSA
562 
563 #if HAVE_VSX
564 INSTANTIATE_TEST_SUITE_P(
565     VSX, VpxPostProcDownAndAcrossMbRowTest,
566     ::testing::Values(vpx_post_proc_down_and_across_mb_row_vsx));
567 
568 INSTANTIATE_TEST_SUITE_P(VSX, VpxMbPostProcAcrossIpTest,
569                          ::testing::Values(vpx_mbpost_proc_across_ip_vsx));
570 
571 INSTANTIATE_TEST_SUITE_P(VSX, VpxMbPostProcDownTest,
572                          ::testing::Values(vpx_mbpost_proc_down_vsx));
573 #endif  // HAVE_VSX
574 
575 }  // namespace
576