1/* 2 * Copyright (c) 2013 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 <math.h> 12#include <stdlib.h> 13#include <string.h> 14#include "test/acm_random.h" 15#include "test/clear_system_state.h" 16#include "test/register_state_check.h" 17#include "test/util.h" 18#include "third_party/googletest/src/include/gtest/gtest.h" 19#include "./vpx_config.h" 20#include "./vp8_rtcd.h" 21#include "vpx/vpx_integer.h" 22#include "vpx_mem/vpx_mem.h" 23 24namespace { 25 26typedef void (*SixtapPredictFunc)(uint8_t *src_ptr, 27 int src_pixels_per_line, 28 int xoffset, 29 int yoffset, 30 uint8_t *dst_ptr, 31 int dst_pitch); 32 33typedef std::tr1::tuple<int, int, SixtapPredictFunc> SixtapPredictParam; 34 35class SixtapPredictTest 36 : public ::testing::TestWithParam<SixtapPredictParam> { 37 public: 38 static void SetUpTestCase() { 39 src_ = reinterpret_cast<uint8_t*>(vpx_memalign(kDataAlignment, kSrcSize)); 40 dst_ = reinterpret_cast<uint8_t*>(vpx_memalign(kDataAlignment, kDstSize)); 41 dst_c_ = reinterpret_cast<uint8_t*>(vpx_memalign(kDataAlignment, kDstSize)); 42 } 43 44 static void TearDownTestCase() { 45 vpx_free(src_); 46 src_ = NULL; 47 vpx_free(dst_); 48 dst_ = NULL; 49 vpx_free(dst_c_); 50 dst_c_ = NULL; 51 } 52 53 virtual void TearDown() { 54 libvpx_test::ClearSystemState(); 55 } 56 57 protected: 58 // Make test arrays big enough for 16x16 functions. Six-tap filters 59 // need 5 extra pixels outside of the macroblock. 60 static const int kSrcStride = 21; 61 static const int kDstStride = 16; 62 static const int kDataAlignment = 16; 63 static const int kSrcSize = kSrcStride * kSrcStride + 1; 64 static const int kDstSize = kDstStride * kDstStride; 65 66 virtual void SetUp() { 67 width_ = GET_PARAM(0); 68 height_ = GET_PARAM(1); 69 sixtap_predict_ = GET_PARAM(2); 70 memset(src_, 0, kSrcSize); 71 memset(dst_, 0, kDstSize); 72 memset(dst_c_, 0, kDstSize); 73 } 74 75 int width_; 76 int height_; 77 SixtapPredictFunc sixtap_predict_; 78 // The src stores the macroblock we will filter on, and makes it 1 byte larger 79 // in order to test unaligned access. The result is stored in dst and dst_c(c 80 // reference code result). 81 static uint8_t* src_; 82 static uint8_t* dst_; 83 static uint8_t* dst_c_; 84}; 85 86uint8_t* SixtapPredictTest::src_ = NULL; 87uint8_t* SixtapPredictTest::dst_ = NULL; 88uint8_t* SixtapPredictTest::dst_c_ = NULL; 89 90TEST_P(SixtapPredictTest, TestWithPresetData) { 91 // Test input 92 static const uint8_t test_data[kSrcSize] = { 93 216, 184, 4, 191, 82, 92, 41, 0, 1, 226, 236, 172, 20, 182, 42, 226, 177, 94 79, 94, 77, 179, 203, 206, 198, 22, 192, 19, 75, 17, 192, 44, 233, 120, 95 48, 168, 203, 141, 210, 203, 143, 180, 184, 59, 201, 110, 102, 171, 32, 96 182, 10, 109, 105, 213, 60, 47, 236, 253, 67, 55, 14, 3, 99, 247, 124, 97 148, 159, 71, 34, 114, 19, 177, 38, 203, 237, 239, 58, 83, 155, 91, 10, 98 166, 201, 115, 124, 5, 163, 104, 2, 231, 160, 16, 234, 4, 8, 103, 153, 99 167, 174, 187, 26, 193, 109, 64, 141, 90, 48, 200, 174, 204, 36, 184, 100 114, 237, 43, 238, 242, 207, 86, 245, 182, 247, 6, 161, 251, 14, 8, 148, 101 182, 182, 79, 208, 120, 188, 17, 6, 23, 65, 206, 197, 13, 242, 126, 128, 102 224, 170, 110, 211, 121, 197, 200, 47, 188, 207, 208, 184, 221, 216, 76, 103 148, 143, 156, 100, 8, 89, 117, 14, 112, 183, 221, 54, 197, 208, 180, 69, 104 176, 94, 180, 131, 215, 121, 76, 7, 54, 28, 216, 238, 249, 176, 58, 142, 105 64, 215, 242, 72, 49, 104, 87, 161, 32, 52, 216, 230, 4, 141, 44, 181, 106 235, 224, 57, 195, 89, 134, 203, 144, 162, 163, 126, 156, 84, 185, 42, 107 148, 145, 29, 221, 194, 134, 52, 100, 166, 105, 60, 140, 110, 201, 184, 108 35, 181, 153, 93, 121, 243, 227, 68, 131, 134, 232, 2, 35, 60, 187, 77, 109 209, 76, 106, 174, 15, 241, 227, 115, 151, 77, 175, 36, 187, 121, 221, 110 223, 47, 118, 61, 168, 105, 32, 237, 236, 167, 213, 238, 202, 17, 170, 111 24, 226, 247, 131, 145, 6, 116, 117, 121, 11, 194, 41, 48, 126, 162, 13, 112 93, 209, 131, 154, 122, 237, 187, 103, 217, 99, 60, 200, 45, 78, 115, 69, 113 49, 106, 200, 194, 112, 60, 56, 234, 72, 251, 19, 120, 121, 182, 134, 215, 114 135, 10, 114, 2, 247, 46, 105, 209, 145, 165, 153, 191, 243, 12, 5, 36, 115 119, 206, 231, 231, 11, 32, 209, 83, 27, 229, 204, 149, 155, 83, 109, 35, 116 93, 223, 37, 84, 14, 142, 37, 160, 52, 191, 96, 40, 204, 101, 77, 67, 52, 117 53, 43, 63, 85, 253, 147, 113, 226, 96, 6, 125, 179, 115, 161, 17, 83, 118 198, 101, 98, 85, 139, 3, 137, 75, 99, 178, 23, 201, 255, 91, 253, 52, 119 134, 60, 138, 131, 208, 251, 101, 48, 2, 227, 228, 118, 132, 245, 202, 120 75, 91, 44, 160, 231, 47, 41, 50, 147, 220, 74, 92, 219, 165, 89, 16 121 }; 122 123 // Expected result 124 static const uint8_t expected_dst[kDstSize] = { 125 117, 102, 74, 135, 42, 98, 175, 206, 70, 73, 222, 197, 50, 24, 39, 49, 38, 126 105, 90, 47, 169, 40, 171, 215, 200, 73, 109, 141, 53, 85, 177, 164, 79, 127 208, 124, 89, 212, 18, 81, 145, 151, 164, 217, 153, 91, 154, 102, 102, 128 159, 75, 164, 152, 136, 51, 213, 219, 186, 116, 193, 224, 186, 36, 231, 129 208, 84, 211, 155, 167, 35, 59, 42, 76, 216, 149, 73, 201, 78, 149, 184, 130 100, 96, 196, 189, 198, 188, 235, 195, 117, 129, 120, 129, 49, 25, 133, 131 113, 69, 221, 114, 70, 143, 99, 157, 108, 189, 140, 78, 6, 55, 65, 240, 132 255, 245, 184, 72, 90, 100, 116, 131, 39, 60, 234, 167, 33, 160, 88, 185, 133 200, 157, 159, 176, 127, 151, 138, 102, 168, 106, 170, 86, 82, 219, 189, 134 76, 33, 115, 197, 106, 96, 198, 136, 97, 141, 237, 151, 98, 137, 191, 135 185, 2, 57, 95, 142, 91, 255, 185, 97, 137, 76, 162, 94, 173, 131, 193, 136 161, 81, 106, 72, 135, 222, 234, 137, 66, 137, 106, 243, 210, 147, 95, 137 15, 137, 110, 85, 66, 16, 96, 167, 147, 150, 173, 203, 140, 118, 196, 138 84, 147, 160, 19, 95, 101, 123, 74, 132, 202, 82, 166, 12, 131, 166, 139 189, 170, 159, 85, 79, 66, 57, 152, 132, 203, 194, 0, 1, 56, 146, 180, 140 224, 156, 28, 83, 181, 79, 76, 80, 46, 160, 175, 59, 106, 43, 87, 75, 141 136, 85, 189, 46, 71, 200, 90 142 }; 143 144 uint8_t *src = const_cast<uint8_t*>(test_data); 145 146 ASM_REGISTER_STATE_CHECK( 147 sixtap_predict_(&src[kSrcStride * 2 + 2 + 1], kSrcStride, 148 2, 2, dst_, kDstStride)); 149 150 for (int i = 0; i < height_; ++i) 151 for (int j = 0; j < width_; ++j) 152 ASSERT_EQ(expected_dst[i * kDstStride + j], dst_[i * kDstStride + j]) 153 << "i==" << (i * width_ + j); 154} 155 156using libvpx_test::ACMRandom; 157 158TEST_P(SixtapPredictTest, TestWithRandomData) { 159 ACMRandom rnd(ACMRandom::DeterministicSeed()); 160 for (int i = 0; i < kSrcSize; ++i) 161 src_[i] = rnd.Rand8(); 162 163 // Run tests for all possible offsets. 164 for (int xoffset = 0; xoffset < 8; ++xoffset) { 165 for (int yoffset = 0; yoffset < 8; ++yoffset) { 166 // Call c reference function. 167 // Move start point to next pixel to test if the function reads 168 // unaligned data correctly. 169 vp8_sixtap_predict16x16_c(&src_[kSrcStride * 2 + 2 + 1], kSrcStride, 170 xoffset, yoffset, dst_c_, kDstStride); 171 172 // Run test. 173 ASM_REGISTER_STATE_CHECK( 174 sixtap_predict_(&src_[kSrcStride * 2 + 2 + 1], kSrcStride, 175 xoffset, yoffset, dst_, kDstStride)); 176 177 for (int i = 0; i < height_; ++i) 178 for (int j = 0; j < width_; ++j) 179 ASSERT_EQ(dst_c_[i * kDstStride + j], dst_[i * kDstStride + j]) 180 << "i==" << (i * width_ + j); 181 } 182 } 183} 184 185using std::tr1::make_tuple; 186 187const SixtapPredictFunc sixtap_16x16_c = vp8_sixtap_predict16x16_c; 188const SixtapPredictFunc sixtap_8x8_c = vp8_sixtap_predict8x8_c; 189const SixtapPredictFunc sixtap_8x4_c = vp8_sixtap_predict8x4_c; 190const SixtapPredictFunc sixtap_4x4_c = vp8_sixtap_predict4x4_c; 191INSTANTIATE_TEST_CASE_P( 192 C, SixtapPredictTest, ::testing::Values( 193 make_tuple(16, 16, sixtap_16x16_c), 194 make_tuple(8, 8, sixtap_8x8_c), 195 make_tuple(8, 4, sixtap_8x4_c), 196 make_tuple(4, 4, sixtap_4x4_c))); 197#if HAVE_NEON 198const SixtapPredictFunc sixtap_16x16_neon = vp8_sixtap_predict16x16_neon; 199const SixtapPredictFunc sixtap_8x8_neon = vp8_sixtap_predict8x8_neon; 200const SixtapPredictFunc sixtap_8x4_neon = vp8_sixtap_predict8x4_neon; 201INSTANTIATE_TEST_CASE_P( 202 DISABLED_NEON, SixtapPredictTest, ::testing::Values( 203 make_tuple(16, 16, sixtap_16x16_neon), 204 make_tuple(8, 8, sixtap_8x8_neon), 205 make_tuple(8, 4, sixtap_8x4_neon))); 206#endif 207#if HAVE_MMX 208const SixtapPredictFunc sixtap_16x16_mmx = vp8_sixtap_predict16x16_mmx; 209const SixtapPredictFunc sixtap_8x8_mmx = vp8_sixtap_predict8x8_mmx; 210const SixtapPredictFunc sixtap_8x4_mmx = vp8_sixtap_predict8x4_mmx; 211const SixtapPredictFunc sixtap_4x4_mmx = vp8_sixtap_predict4x4_mmx; 212INSTANTIATE_TEST_CASE_P( 213 MMX, SixtapPredictTest, ::testing::Values( 214 make_tuple(16, 16, sixtap_16x16_mmx), 215 make_tuple(8, 8, sixtap_8x8_mmx), 216 make_tuple(8, 4, sixtap_8x4_mmx), 217 make_tuple(4, 4, sixtap_4x4_mmx))); 218#endif 219#if HAVE_SSE2 220const SixtapPredictFunc sixtap_16x16_sse2 = vp8_sixtap_predict16x16_sse2; 221const SixtapPredictFunc sixtap_8x8_sse2 = vp8_sixtap_predict8x8_sse2; 222const SixtapPredictFunc sixtap_8x4_sse2 = vp8_sixtap_predict8x4_sse2; 223INSTANTIATE_TEST_CASE_P( 224 SSE2, SixtapPredictTest, ::testing::Values( 225 make_tuple(16, 16, sixtap_16x16_sse2), 226 make_tuple(8, 8, sixtap_8x8_sse2), 227 make_tuple(8, 4, sixtap_8x4_sse2))); 228#endif 229#if HAVE_SSSE3 230const SixtapPredictFunc sixtap_16x16_ssse3 = vp8_sixtap_predict16x16_ssse3; 231const SixtapPredictFunc sixtap_8x8_ssse3 = vp8_sixtap_predict8x8_ssse3; 232const SixtapPredictFunc sixtap_8x4_ssse3 = vp8_sixtap_predict8x4_ssse3; 233const SixtapPredictFunc sixtap_4x4_ssse3 = vp8_sixtap_predict4x4_ssse3; 234INSTANTIATE_TEST_CASE_P( 235 SSSE3, SixtapPredictTest, ::testing::Values( 236 make_tuple(16, 16, sixtap_16x16_ssse3), 237 make_tuple(8, 8, sixtap_8x8_ssse3), 238 make_tuple(8, 4, sixtap_8x4_ssse3), 239 make_tuple(4, 4, sixtap_4x4_ssse3))); 240#endif 241} // namespace 242