diff --git a/test/sad_test.cc b/test/sad_test.cc index e0c5cfefa01398648a695bc3922c86977db07219..165e2c8f0c58182513ba2a63105f70848c5ad63f 100644 --- a/test/sad_test.cc +++ b/test/sad_test.cc @@ -37,14 +37,22 @@ typedef unsigned int (*sad_m_by_n_fn_t)(const unsigned char *source_ptr, int reference_stride, unsigned int max_sad); +typedef void (*sad_n_by_n_by_4_fn_t)(const uint8_t *src_ptr, + int src_stride, + const unsigned char * const ref_ptr[], + int ref_stride, + unsigned int *sad_array); + using libvpx_test::ACMRandom; namespace { -class SADTest : public PARAMS(int, int, sad_m_by_n_fn_t) { +class SADTestBase : public ::testing::Test { public: + SADTestBase(int width, int height) : width_(width), height_(height) {} + static void SetUpTestCase() { source_data_ = reinterpret_cast<uint8_t*>( - vpx_memalign(kDataAlignment, kDataBufferSize)); + vpx_memalign(kDataAlignment, kDataBlockSize)); reference_data_ = reinterpret_cast<uint8_t*>( vpx_memalign(kDataAlignment, kDataBufferSize)); } @@ -59,35 +67,29 @@ class SADTest : public PARAMS(int, int, sad_m_by_n_fn_t) { protected: // Handle blocks up to 4 blocks 64x64 with stride up to 128 static const int kDataAlignment = 16; - static const int kDataBufferSize = 4 * 64 * 128; + static const int kDataBlockSize = 64 * 128; + static const int kDataBufferSize = 4 * kDataBlockSize; virtual void SetUp() { - sad_fn_ = GET_PARAM(2); - height_ = GET_PARAM(1); - width_ = GET_PARAM(0); source_stride_ = (width_ + 31) & ~31; reference_stride_ = width_ * 2; rnd_.Reset(ACMRandom::DeterministicSeed()); } - sad_m_by_n_fn_t sad_fn_; - virtual unsigned int SAD(unsigned int max_sad) { - unsigned int ret; - REGISTER_STATE_CHECK(ret = sad_fn_(source_data_, source_stride_, - reference_data_, reference_stride_, - max_sad)); - return ret; + virtual uint8_t* GetReference(int block_idx) { + return reference_data_ + block_idx * kDataBlockSize; } // Sum of Absolute Differences. Given two blocks, calculate the absolute // difference between two pixels in the same relative location; accumulate. - unsigned int ReferenceSAD(unsigned int max_sad) { + unsigned int ReferenceSAD(unsigned int max_sad, int block_idx = 0) { unsigned int sad = 0; + const uint8_t* const reference = GetReference(block_idx); for (int h = 0; h < height_; ++h) { for (int w = 0; w < width_; ++w) { sad += abs(source_data_[h * source_stride_ + w] - - reference_data_[h * reference_stride_ + w]); + - reference[h * reference_stride_ + w]); } if (sad > max_sad) { break; @@ -112,6 +114,32 @@ class SADTest : public PARAMS(int, int, sad_m_by_n_fn_t) { } } + int width_, height_; + static uint8_t* source_data_; + int source_stride_; + static uint8_t* reference_data_; + int reference_stride_; + + ACMRandom rnd_; +}; + +class SADTest : public SADTestBase, + public ::testing::WithParamInterface< + std::tr1::tuple<int, int, sad_m_by_n_fn_t> > { + public: + SADTest() : SADTestBase(GET_PARAM(0), GET_PARAM(1)) {} + + protected: + unsigned int SAD(unsigned int max_sad, int block_idx = 0) { + unsigned int ret; + const uint8_t* const reference = GetReference(block_idx); + + REGISTER_STATE_CHECK(ret = GET_PARAM(2)(source_data_, source_stride_, + reference, reference_stride_, + max_sad)); + return ret; + } + void CheckSad(unsigned int max_sad) { unsigned int reference_sad, exp_sad; @@ -125,18 +153,38 @@ class SADTest : public PARAMS(int, int, sad_m_by_n_fn_t) { ASSERT_GE(exp_sad, reference_sad); } } +}; - int height_, width_; - static uint8_t* source_data_; - int source_stride_; - static uint8_t* reference_data_; - int reference_stride_; +class SADx4Test : public SADTestBase, + public ::testing::WithParamInterface< + std::tr1::tuple<int, int, sad_n_by_n_by_4_fn_t> > { + public: + SADx4Test() : SADTestBase(GET_PARAM(0), GET_PARAM(1)) {} - ACMRandom rnd_; + protected: + void SADs(unsigned int *results) { + const uint8_t* refs[] = {GetReference(0), GetReference(1), + GetReference(2), GetReference(3)}; + + REGISTER_STATE_CHECK(GET_PARAM(2)(source_data_, source_stride_, + refs, reference_stride_, + results)); + } + + void CheckSADs() { + unsigned int reference_sad, exp_sad[4]; + + SADs(exp_sad); + for (int block = 0; block < 4; block++) { + reference_sad = ReferenceSAD(UINT_MAX, block); + + EXPECT_EQ(exp_sad[block], reference_sad) << "block " << block; + } + } }; -uint8_t* SADTest::source_data_ = NULL; -uint8_t* SADTest::reference_data_ = NULL; +uint8_t* SADTestBase::source_data_ = NULL; +uint8_t* SADTestBase::reference_data_ = NULL; TEST_P(SADTest, MaxRef) { FillConstant(source_data_, source_stride_, 0); @@ -144,12 +192,30 @@ TEST_P(SADTest, MaxRef) { CheckSad(UINT_MAX); } +TEST_P(SADx4Test, MaxRef) { + FillConstant(source_data_, source_stride_, 0); + FillConstant(GetReference(0), reference_stride_, 255); + FillConstant(GetReference(1), reference_stride_, 255); + FillConstant(GetReference(2), reference_stride_, 255); + FillConstant(GetReference(3), reference_stride_, 255); + CheckSADs(); +} + TEST_P(SADTest, MaxSrc) { FillConstant(source_data_, source_stride_, 255); FillConstant(reference_data_, reference_stride_, 0); CheckSad(UINT_MAX); } +TEST_P(SADx4Test, MaxSrc) { + FillConstant(source_data_, source_stride_, 255); + FillConstant(GetReference(0), reference_stride_, 0); + FillConstant(GetReference(1), reference_stride_, 0); + FillConstant(GetReference(2), reference_stride_, 0); + FillConstant(GetReference(3), reference_stride_, 0); + CheckSADs(); +} + TEST_P(SADTest, ShortRef) { int tmp_stride = reference_stride_; reference_stride_ >>= 1; @@ -159,6 +225,18 @@ TEST_P(SADTest, ShortRef) { reference_stride_ = tmp_stride; } +TEST_P(SADx4Test, ShortRef) { + int tmp_stride = reference_stride_; + reference_stride_ >>= 1; + FillRandom(source_data_, source_stride_); + FillRandom(GetReference(0), reference_stride_); + FillRandom(GetReference(1), reference_stride_); + FillRandom(GetReference(2), reference_stride_); + FillRandom(GetReference(3), reference_stride_); + CheckSADs(); + reference_stride_ = tmp_stride; +} + TEST_P(SADTest, UnalignedRef) { // The reference frame, but not the source frame, may be unaligned for // certain types of searches. @@ -170,6 +248,20 @@ TEST_P(SADTest, UnalignedRef) { reference_stride_ = tmp_stride; } +TEST_P(SADx4Test, UnalignedRef) { + // The reference frame, but not the source frame, may be unaligned for + // certain types of searches. + int tmp_stride = reference_stride_; + reference_stride_ -= 1; + FillRandom(source_data_, source_stride_); + FillRandom(GetReference(0), reference_stride_); + FillRandom(GetReference(1), reference_stride_); + FillRandom(GetReference(2), reference_stride_); + FillRandom(GetReference(3), reference_stride_); + CheckSADs(); + reference_stride_ = tmp_stride; +} + TEST_P(SADTest, ShortSrc) { int tmp_stride = source_stride_; source_stride_ >>= 1; @@ -179,6 +271,18 @@ TEST_P(SADTest, ShortSrc) { source_stride_ = tmp_stride; } +TEST_P(SADx4Test, ShortSrc) { + int tmp_stride = source_stride_; + source_stride_ >>= 1; + FillRandom(source_data_, source_stride_); + FillRandom(GetReference(0), reference_stride_); + FillRandom(GetReference(1), reference_stride_); + FillRandom(GetReference(2), reference_stride_); + FillRandom(GetReference(3), reference_stride_); + CheckSADs(); + source_stride_ = tmp_stride; +} + TEST_P(SADTest, MaxSAD) { // Verify that, when max_sad is set, the implementation does not return a // value lower than the reference. @@ -231,6 +335,20 @@ INSTANTIATE_TEST_CASE_P(C, SADTest, ::testing::Values( #endif )); +#if CONFIG_VP9_ENCODER +const sad_n_by_n_by_4_fn_t sad_64x64x4d_c = vp9_sad64x64x4d_c; +const sad_n_by_n_by_4_fn_t sad_32x32x4d_c = vp9_sad32x32x4d_c; +const sad_n_by_n_by_4_fn_t sad_16x16x4d_c = vp9_sad16x16x4d_c; +const sad_n_by_n_by_4_fn_t sad_8x8x4d_c = vp9_sad8x8x4d_c; +const sad_n_by_n_by_4_fn_t sad_4x4x4d_c = vp9_sad4x4x4d_c; +INSTANTIATE_TEST_CASE_P(C, SADx4Test, ::testing::Values( + make_tuple(64, 64, sad_64x64x4d_c), + make_tuple(32, 32, sad_32x32x4d_c), + make_tuple(16, 16, sad_16x16x4d_c), + make_tuple(8, 8, sad_8x8x4d_c), + make_tuple(4, 4, sad_4x4x4d_c))); +#endif + // ARM tests #if HAVE_MEDIA const sad_m_by_n_fn_t sad_16x16_armv6 = vp8_sad16x16_armv6; @@ -293,6 +411,10 @@ INSTANTIATE_TEST_CASE_P(MMX, SADTest, ::testing::Values( const sad_m_by_n_fn_t sad_4x4_sse_vp9 = vp9_sad4x4_sse; INSTANTIATE_TEST_CASE_P(SSE, SADTest, ::testing::Values( make_tuple(4, 4, sad_4x4_sse_vp9))); + +const sad_n_by_n_by_4_fn_t sad_4x4x4d_sse = vp9_sad4x4x4d_sse; +INSTANTIATE_TEST_CASE_P(SSE, SADx4Test, ::testing::Values( + make_tuple(4, 4, sad_4x4x4d_sse))); #endif #endif @@ -330,6 +452,38 @@ INSTANTIATE_TEST_CASE_P(SSE2, SADTest, ::testing::Values( make_tuple(8, 8, sad_8x8_sse2_vp9) #endif )); + +#if CONFIG_VP9_ENCODER +const sad_n_by_n_by_4_fn_t sad_64x64x4d_sse2 = vp9_sad64x64x4d_sse2; +const sad_n_by_n_by_4_fn_t sad_32x32x4d_sse2 = vp9_sad32x32x4d_sse2; +const sad_n_by_n_by_4_fn_t sad_16x16x4d_sse2 = vp9_sad16x16x4d_sse2; +const sad_n_by_n_by_4_fn_t sad_16x8x4d_sse2 = vp9_sad16x8x4d_sse2; +const sad_n_by_n_by_4_fn_t sad_8x16x4d_sse2 = vp9_sad8x16x4d_sse2; +const sad_n_by_n_by_4_fn_t sad_8x8x4d_sse2 = vp9_sad8x8x4d_sse2; +INSTANTIATE_TEST_CASE_P(SSE2, SADx4Test, ::testing::Values( + make_tuple(64, 64, sad_64x64x4d_sse2), + make_tuple(32, 32, sad_32x32x4d_sse2), + make_tuple(16, 16, sad_16x16x4d_sse2), + make_tuple(16, 8, sad_16x8x4d_sse2), + make_tuple(8, 16, sad_8x16x4d_sse2), + make_tuple(8, 8, sad_8x8x4d_sse2))); +#endif +#endif + +#if HAVE_SSE3 +#if CONFIG_VP8_ENCODER +const sad_n_by_n_by_4_fn_t sad_16x16x4d_sse3 = vp8_sad16x16x4d_sse3; +const sad_n_by_n_by_4_fn_t sad_16x8x4d_sse3 = vp8_sad16x8x4d_sse3; +const sad_n_by_n_by_4_fn_t sad_8x16x4d_sse3 = vp8_sad8x16x4d_sse3; +const sad_n_by_n_by_4_fn_t sad_8x8x4d_sse3 = vp8_sad8x8x4d_sse3; +const sad_n_by_n_by_4_fn_t sad_4x4x4d_sse3 = vp8_sad4x4x4d_sse3; +INSTANTIATE_TEST_CASE_P(SSE3, SADx4Test, ::testing::Values( + make_tuple(16, 16, sad_16x16x4d_sse3), + make_tuple(16, 8, sad_16x8x4d_sse3), + make_tuple(8, 16, sad_8x16x4d_sse3), + make_tuple(8, 8, sad_8x8x4d_sse3), + make_tuple(4, 4, sad_4x4x4d_sse3))); +#endif #endif #if HAVE_SSSE3 diff --git a/vp9/common/vp9_rtcd_defs.sh b/vp9/common/vp9_rtcd_defs.sh index b9acadea7f0c6b869ccda0c01dbc76a79aa3c146..e6dcff4d1a16c9a2cbefbd8af7b2d8e34b3c6eef 100644 --- a/vp9/common/vp9_rtcd_defs.sh +++ b/vp9/common/vp9_rtcd_defs.sh @@ -470,25 +470,25 @@ specialize vp9_sad8x8x8 sse4 prototype void vp9_sad4x4x8 "const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride, uint32_t *sad_array" specialize vp9_sad4x4x8 sse4 -prototype void vp9_sad64x64x4d "const uint8_t *src_ptr, int src_stride, const uint8_t **ref_ptr, int ref_stride, unsigned int *sad_array" +prototype void vp9_sad64x64x4d "const uint8_t *src_ptr, int src_stride, const uint8_t* const ref_ptr[], int ref_stride, unsigned int *sad_array" specialize vp9_sad64x64x4d sse2 -prototype void vp9_sad32x32x4d "const uint8_t *src_ptr, int src_stride, const uint8_t **ref_ptr, int ref_stride, unsigned int *sad_array" +prototype void vp9_sad32x32x4d "const uint8_t *src_ptr, int src_stride, const uint8_t* const ref_ptr[], int ref_stride, unsigned int *sad_array" specialize vp9_sad32x32x4d sse2 -prototype void vp9_sad16x16x4d "const uint8_t *src_ptr, int src_stride, const uint8_t **ref_ptr, int ref_stride, unsigned int *sad_array" +prototype void vp9_sad16x16x4d "const uint8_t *src_ptr, int src_stride, const uint8_t* const ref_ptr[], int ref_stride, unsigned int *sad_array" specialize vp9_sad16x16x4d sse2 -prototype void vp9_sad16x8x4d "const uint8_t *src_ptr, int src_stride, const uint8_t **ref_ptr, int ref_stride, unsigned int *sad_array" +prototype void vp9_sad16x8x4d "const uint8_t *src_ptr, int src_stride, const uint8_t* const ref_ptr[], int ref_stride, unsigned int *sad_array" specialize vp9_sad16x8x4d sse2 -prototype void vp9_sad8x16x4d "const uint8_t *src_ptr, int src_stride, const uint8_t **ref_ptr, int ref_stride, unsigned int *sad_array" +prototype void vp9_sad8x16x4d "const uint8_t *src_ptr, int src_stride, const uint8_t* const ref_ptr[], int ref_stride, unsigned int *sad_array" specialize vp9_sad8x16x4d sse2 -prototype void vp9_sad8x8x4d "const uint8_t *src_ptr, int src_stride, const uint8_t **ref_ptr, int ref_stride, unsigned int *sad_array" +prototype void vp9_sad8x8x4d "const uint8_t *src_ptr, int src_stride, const uint8_t* const ref_ptr[], int ref_stride, unsigned int *sad_array" specialize vp9_sad8x8x4d sse2 -prototype void vp9_sad4x4x4d "const uint8_t *src_ptr, int src_stride, const uint8_t **ref_ptr, int ref_stride, unsigned int *sad_array" +prototype void vp9_sad4x4x4d "const uint8_t *src_ptr, int src_stride, const uint8_t* const ref_ptr[], int ref_stride, unsigned int *sad_array" specialize vp9_sad4x4x4d sse prototype unsigned int vp9_sub_pixel_mse16x16 "const uint8_t *src_ptr, int src_pixels_per_line, int xoffset, int yoffset, const uint8_t *dst_ptr, int dst_pixels_per_line, unsigned int *sse" specialize vp9_sub_pixel_mse16x16 sse2 mmx diff --git a/vp9/encoder/vp9_sad_c.c b/vp9/encoder/vp9_sad_c.c index dc21f02f638b804ead98c58fb9b2889ee9fc2791..af5526dce333bf133eff44b957ea3c63951ab766 100644 --- a/vp9/encoder/vp9_sad_c.c +++ b/vp9/encoder/vp9_sad_c.c @@ -383,7 +383,7 @@ void vp9_sad4x4x8_c(const uint8_t *src_ptr, void vp9_sad64x64x4d_c(const uint8_t *src_ptr, int src_stride, - const uint8_t *ref_ptr[], + const uint8_t* const ref_ptr[], int ref_stride, unsigned int *sad_array) { sad_array[0] = vp9_sad64x64(src_ptr, src_stride, @@ -398,7 +398,7 @@ void vp9_sad64x64x4d_c(const uint8_t *src_ptr, void vp9_sad32x32x4d_c(const uint8_t *src_ptr, int src_stride, - const uint8_t *ref_ptr[], + const uint8_t* const ref_ptr[], int ref_stride, unsigned int *sad_array) { sad_array[0] = vp9_sad32x32(src_ptr, src_stride, @@ -413,7 +413,7 @@ void vp9_sad32x32x4d_c(const uint8_t *src_ptr, void vp9_sad16x16x4d_c(const uint8_t *src_ptr, int src_stride, - const uint8_t *ref_ptr[], + const uint8_t* const ref_ptr[], int ref_stride, unsigned int *sad_array) { sad_array[0] = vp9_sad16x16(src_ptr, src_stride, @@ -428,7 +428,7 @@ void vp9_sad16x16x4d_c(const uint8_t *src_ptr, void vp9_sad16x8x4d_c(const uint8_t *src_ptr, int src_stride, - const uint8_t *ref_ptr[], + const uint8_t* const ref_ptr[], int ref_stride, unsigned int *sad_array) { sad_array[0] = vp9_sad16x8(src_ptr, src_stride, @@ -443,7 +443,7 @@ void vp9_sad16x8x4d_c(const uint8_t *src_ptr, void vp9_sad8x8x4d_c(const uint8_t *src_ptr, int src_stride, - const uint8_t *ref_ptr[], + const uint8_t* const ref_ptr[], int ref_stride, unsigned int *sad_array) { sad_array[0] = vp9_sad8x8(src_ptr, src_stride, @@ -458,7 +458,7 @@ void vp9_sad8x8x4d_c(const uint8_t *src_ptr, void vp9_sad8x16x4d_c(const uint8_t *src_ptr, int src_stride, - const uint8_t *ref_ptr[], + const uint8_t* const ref_ptr[], int ref_stride, unsigned int *sad_array) { sad_array[0] = vp9_sad8x16(src_ptr, src_stride, @@ -473,7 +473,7 @@ void vp9_sad8x16x4d_c(const uint8_t *src_ptr, void vp9_sad4x4x4d_c(const uint8_t *src_ptr, int src_stride, - const uint8_t *ref_ptr[], + const uint8_t* const ref_ptr[], int ref_stride, unsigned int *sad_array) { sad_array[0] = vp9_sad4x4(src_ptr, src_stride, diff --git a/vp9/encoder/vp9_variance.h b/vp9/encoder/vp9_variance.h index 7120c5fe7e1fb56140e2bdd9a7eeac1c80d917ef..13dabbda41d711a8dce115cf2892182450083a14 100644 --- a/vp9/encoder/vp9_variance.h +++ b/vp9/encoder/vp9_variance.h @@ -33,7 +33,7 @@ typedef void (*vp9_sad_multi1_fn_t)(const uint8_t *src_ptr, typedef void (*vp9_sad_multi_d_fn_t)(const uint8_t *src_ptr, int source_stride, - const uint8_t ** ref_ptr, + const uint8_t* const ref_ptr[], int ref_stride, unsigned int *sad_array); typedef unsigned int (*vp9_variance_fn_t)(const uint8_t *src_ptr,