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