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 {
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) {
}
}
- 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
}
}
}
}
+ 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_;
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()) {}
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;
}
}
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);
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);
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[] = {
};
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
#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