shithub: libvpx

Download patch

ref: a6622470704b5252e415db18263cb5f8ee194800
parent: 53dc2d9d96d2c1bf397b2c1293acaab708371e7d
author: Angie Chiang <angiebird@google.com>
date: Sun Jul 14 04:59:18 EDT 2019

Add unit test for vpx_sadMxNx8

Change-Id: Ica85e3738708e2a6cc7388fd2cbf6a8840a540d5

--- a/test/sad_test.cc
+++ b/test/sad_test.cc
@@ -48,6 +48,12 @@
                              unsigned int *sad_array);
 typedef TestParams<SadMxNx4Func> SadMxNx4Param;
 
+typedef void (*SadMxNx8Func)(const uint8_t *src_ptr, int src_stride,
+                             const uint8_t *ref_ptr, int ref_stride,
+                             unsigned int *sad_array);
+
+typedef TestParams<SadMxNx8Func> SadMxNx8Param;
+
 using libvpx_test::ACMRandom;
 
 namespace {
@@ -114,25 +120,36 @@
   static const int kDataBlockSize = 64 * 128;
   static const int kDataBufferSize = 4 * kDataBlockSize;
 
-  uint8_t *GetReference(int block_idx) const {
+  int GetBlockRefOffset(int block_idx) const {
+    return block_idx * kDataBlockSize;
+  }
+
+  uint8_t *GetReferenceFromOffset(int ref_offset) const {
+    assert((params_.height - 1) * reference_stride_ + params_.width - 1 +
+               ref_offset <
+           kDataBufferSize);
 #if CONFIG_VP9_HIGHBITDEPTH
     if (use_high_bit_depth_) {
       return CONVERT_TO_BYTEPTR(CONVERT_TO_SHORTPTR(reference_data_) +
-                                block_idx * kDataBlockSize);
+                                ref_offset);
     }
 #endif  // CONFIG_VP9_HIGHBITDEPTH
-    return reference_data_ + block_idx * kDataBlockSize;
+    return reference_data_ + ref_offset;
   }
 
+  uint8_t *GetReference(int block_idx) const {
+    return GetReferenceFromOffset(GetBlockRefOffset(block_idx));
+  }
+
   // Sum of Absolute Differences. Given two blocks, calculate the absolute
   // difference between two pixels in the same relative location; accumulate.
-  uint32_t ReferenceSAD(int block_idx) const {
+  uint32_t ReferenceSAD(int ref_offset) const {
     uint32_t sad = 0;
-    const uint8_t *const reference8 = GetReference(block_idx);
+    const uint8_t *const reference8 = GetReferenceFromOffset(ref_offset);
     const uint8_t *const source8 = source_data_;
 #if CONFIG_VP9_HIGHBITDEPTH
     const uint16_t *const reference16 =
-        CONVERT_TO_SHORTPTR(GetReference(block_idx));
+        CONVERT_TO_SHORTPTR(GetReferenceFromOffset(ref_offset));
     const uint16_t *const source16 = CONVERT_TO_SHORTPTR(source_data_);
 #endif  // CONFIG_VP9_HIGHBITDEPTH
     for (int h = 0; h < params_.height; ++h) {
@@ -203,18 +220,18 @@
     }
   }
 
-  void FillRandom(uint8_t *data, int stride) {
+  void FillRandomWH(uint8_t *data, int stride, int w, int h) {
     uint8_t *data8 = data;
 #if CONFIG_VP9_HIGHBITDEPTH
     uint16_t *data16 = CONVERT_TO_SHORTPTR(data);
 #endif  // CONFIG_VP9_HIGHBITDEPTH
-    for (int h = 0; h < params_.height; ++h) {
-      for (int w = 0; w < params_.width; ++w) {
+    for (int r = 0; r < h; ++r) {
+      for (int c = 0; c < w; ++c) {
         if (!use_high_bit_depth_) {
-          data8[h * stride + w] = rnd_.Rand8();
+          data8[r * stride + c] = rnd_.Rand8();
 #if CONFIG_VP9_HIGHBITDEPTH
         } else {
-          data16[h * stride + w] = rnd_.Rand16() & mask_;
+          data16[r * stride + c] = rnd_.Rand16() & mask_;
 #endif  // CONFIG_VP9_HIGHBITDEPTH
         }
       }
@@ -221,6 +238,10 @@
     }
   }
 
+  void FillRandom(uint8_t *data, int stride) {
+    FillRandomWH(data, stride, params_.width, params_.height);
+  }
+
   uint32_t mask_;
   vpx_bit_depth_t bit_depth_;
   int source_stride_;
@@ -241,6 +262,29 @@
   ParamType params_;
 };
 
+class SADx8Test : public SADTestBase<SadMxNx8Param> {
+ public:
+  SADx8Test() : SADTestBase(GetParam()) {}
+
+ protected:
+  void SADs(unsigned int *results) const {
+    const uint8_t *reference = GetReferenceFromOffset(0);
+
+    ASM_REGISTER_STATE_CHECK(params_.func(
+        source_data_, source_stride_, reference, reference_stride_, results));
+  }
+
+  void CheckSADs() const {
+    uint32_t reference_sad, exp_sad[8];
+
+    SADs(exp_sad);
+    for (int offset = 0; offset < 8; ++offset) {
+      reference_sad = ReferenceSAD(offset);
+      EXPECT_EQ(reference_sad, exp_sad[offset]) << "offset " << offset;
+    }
+  }
+};
+
 class SADx4Test : public SADTestBase<SadMxNx4Param> {
  public:
   SADx4Test() : SADTestBase(GetParam()) {}
@@ -259,7 +303,7 @@
 
     SADs(exp_sad);
     for (int block = 0; block < 4; ++block) {
-      reference_sad = ReferenceSAD(block);
+      reference_sad = ReferenceSAD(GetBlockRefOffset(block));
 
       EXPECT_EQ(reference_sad, exp_sad[block]) << "block " << block;
     }
@@ -281,7 +325,7 @@
   }
 
   void CheckSAD() const {
-    const unsigned int reference_sad = ReferenceSAD(0);
+    const unsigned int reference_sad = ReferenceSAD(GetBlockRefOffset(0));
     const unsigned int exp_sad = SAD(0);
 
     ASSERT_EQ(reference_sad, exp_sad);
@@ -498,7 +542,7 @@
   vpx_usec_timer_start(&timer);
   for (int i = 0; i < kCountSpeedTestBlock; ++i) {
     for (int block = 0; block < 4; ++block) {
-      reference_sad[block] = ReferenceSAD(block);
+      reference_sad[block] = ReferenceSAD(GetBlockRefOffset(block));
     }
   }
   vpx_usec_timer_mark(&timer);
@@ -513,6 +557,13 @@
   reference_stride_ = tmp_stride;
 }
 
+TEST_P(SADx8Test, Regular) {
+  FillRandomWH(source_data_, source_stride_, params_.width, params_.height);
+  FillRandomWH(GetReferenceFromOffset(0), reference_stride_, params_.width + 8,
+               params_.height);
+  CheckSADs();
+}
+
 //------------------------------------------------------------------------------
 // C functions
 const SadMxNParam c_tests[] = {
@@ -689,6 +740,24 @@
 };
 INSTANTIATE_TEST_CASE_P(C, SADx4Test, ::testing::ValuesIn(x4d_c_tests));
 
+// TODO(angiebird): implement the marked-down sad functions
+const SadMxNx8Param x8_c_tests[] = {
+  // SadMxNx8Param(64, 64, &vpx_sad64x64x8_c),
+  // SadMxNx8Param(64, 32, &vpx_sad64x32x8_c),
+  // SadMxNx8Param(32, 64, &vpx_sad32x64x8_c),
+  // SadMxNx8Param(32, 32, &vpx_sad32x32x8_c),
+  // SadMxNx8Param(32, 16, &vpx_sad32x16x8_c),
+  // SadMxNx8Param(16, 32, &vpx_sad16x32x8_c),
+  SadMxNx8Param(16, 16, &vpx_sad16x16x8_c),
+  SadMxNx8Param(16, 8, &vpx_sad16x8x8_c),
+  SadMxNx8Param(8, 16, &vpx_sad8x16x8_c),
+  SadMxNx8Param(8, 8, &vpx_sad8x8x8_c),
+  // SadMxNx8Param(8, 4, &vpx_sad8x4x8_c),
+  // SadMxNx8Param(4, 8, &vpx_sad4x8x8_c),
+  SadMxNx8Param(4, 4, &vpx_sad4x4x8_c),
+};
+INSTANTIATE_TEST_CASE_P(C, SADx8Test, ::testing::ValuesIn(x8_c_tests));
+
 //------------------------------------------------------------------------------
 // ARM functions
 #if HAVE_NEON
@@ -917,7 +986,15 @@
 #endif  // HAVE_SSSE3
 
 #if HAVE_SSE4_1
-// Only functions are x8, which do not have tests.
+const SadMxNx8Param x8_sse4_1_tests[] = {
+  SadMxNx8Param(16, 16, &vpx_sad16x16x8_sse4_1),
+  SadMxNx8Param(16, 8, &vpx_sad16x8x8_sse4_1),
+  SadMxNx8Param(8, 16, &vpx_sad8x16x8_sse4_1),
+  SadMxNx8Param(8, 8, &vpx_sad8x8x8_sse4_1),
+  SadMxNx8Param(4, 4, &vpx_sad4x4x8_sse4_1),
+};
+INSTANTIATE_TEST_CASE_P(SSE4_1, SADx8Test,
+                        ::testing::ValuesIn(x8_sse4_1_tests));
 #endif  // HAVE_SSE4_1
 
 #if HAVE_AVX2