Showing the changes to test/processing/ProcessUT_DownSample.cpp (1 of 3 files). Show all
Unified · Split
| @@ -0,0 +1,275 @@ | |||
| 1 | #include <gtest/gtest.h> | ||
| 2 | #include "cpu.h" | ||
| 3 | #include "cpu_core.h" | ||
| 4 | #include "util.h" | ||
| 5 | #include "macros.h" | ||
| 6 | #include "IWelsVP.h" | ||
| 7 | #include "downsample.h" | ||
| 8 | |||
| 9 | using namespace nsWelsVP; | ||
| 10 | |||
| 11 | void DyadicBilinearDownsampler_ref (uint8_t* pDst, const int32_t kiDstStride, | ||
| 12 | uint8_t* pSrc, const int32_t kiSrcStride, | ||
| 13 | const int32_t kiSrcWidth, const int32_t kiSrcHeight) { | ||
| 14 | uint8_t* pDstLine = pDst; | ||
| 15 | uint8_t* pSrcLine = pSrc; | ||
| 16 | const int32_t kiSrcStridex2 = kiSrcStride << 1; | ||
| 17 | const int32_t kiDstWidth = kiSrcWidth >> 1; | ||
| 18 | const int32_t kiDstHeight = kiSrcHeight >> 1; | ||
| 19 | |||
| 20 | for (int32_t j = 0; j < kiDstHeight; j ++) { | ||
| 21 | for (int32_t i = 0; i < kiDstWidth; i ++) { | ||
| 22 | const int32_t kiSrcX = i << 1; | ||
| 23 | const int32_t kiTempRow1 = (pSrcLine[kiSrcX] + pSrcLine[kiSrcX + 1] + 1) >> 1; | ||
| 24 | const int32_t kiTempRow2 = (pSrcLine[kiSrcX + kiSrcStride] + pSrcLine[kiSrcX + kiSrcStride + 1] + 1) >> 1; | ||
| 25 | |||
| 26 | pDstLine[i] = (uint8_t) ((kiTempRow1 + kiTempRow2 + 1) >> 1); | ||
| 27 | } | ||
| 28 | pDstLine += kiDstStride; | ||
| 29 | pSrcLine += kiSrcStridex2; | ||
| 30 | } | ||
| 31 | } | ||
| 32 | |||
| 33 | void GeneralBilinearFastDownsampler_ref (uint8_t* pDst, const int32_t kiDstStride, const int32_t kiDstWidth, const int32_t kiDstHeight, | ||
| 34 | uint8_t* pSrc, const int32_t kiSrcStride, const int32_t kiSrcWidth, const int32_t kiSrcHeight) { | ||
| 35 | const uint32_t kuiScaleBitWidth = 16, kuiScaleBitHeight = 15; | ||
| 36 | const uint32_t kuiScaleWidth = (1 << kuiScaleBitWidth), kuiScaleHeight = (1 << kuiScaleBitHeight); | ||
| 37 | int32_t fScalex = WELS_ROUND ((float)kiSrcWidth / (float)kiDstWidth * kuiScaleWidth); | ||
| 38 | int32_t fScaley = WELS_ROUND ((float)kiSrcHeight / (float)kiDstHeight * kuiScaleHeight); | ||
| 39 | uint32_t x; | ||
| 40 | int32_t iYInverse, iXInverse; | ||
| 41 | |||
| 42 | uint8_t* pByDst = pDst; | ||
| 43 | uint8_t* pByLineDst = pDst; | ||
| 44 | |||
| 45 | iYInverse = 1 << (kuiScaleBitHeight - 1); | ||
| 46 | for (int32_t i = 0; i < kiDstHeight - 1; i++) { | ||
| 47 | int32_t iYy = iYInverse >> kuiScaleBitHeight; | ||
| 48 | int32_t fv = iYInverse & (kuiScaleHeight - 1); | ||
| 49 | |||
| 50 | uint8_t* pBySrc = pSrc + iYy * kiSrcStride; | ||
| 51 | |||
| 52 | pByDst = pByLineDst; | ||
| 53 | iXInverse = 1 << (kuiScaleBitWidth - 1); | ||
| 54 | for (int32_t j = 0; j < kiDstWidth - 1; j++) { | ||
| 55 | int32_t iXx = iXInverse >> kuiScaleBitWidth; | ||
| 56 | int32_t iFu = iXInverse & (kuiScaleWidth - 1); | ||
| 57 | |||
| 58 | uint8_t* pByCurrent = pBySrc + iXx; | ||
| 59 | uint8_t a, b, c, d; | ||
| 60 | |||
| 61 | a = *pByCurrent; | ||
| 62 | b = * (pByCurrent + 1); | ||
| 63 | c = * (pByCurrent + kiSrcStride); | ||
| 64 | d = * (pByCurrent + kiSrcStride + 1); | ||
| 65 | |||
| 66 | x = (((uint32_t) (kuiScaleWidth - 1 - iFu)) * (kuiScaleHeight - 1 - fv) >> kuiScaleBitWidth) * a; | ||
| 67 | x += (((uint32_t) (iFu)) * (kuiScaleHeight - 1 - fv) >> kuiScaleBitWidth) * b; | ||
| 68 | x += (((uint32_t) (kuiScaleWidth - 1 - iFu)) * (fv) >> kuiScaleBitWidth) * c; | ||
| 69 | x += (((uint32_t) (iFu)) * (fv) >> kuiScaleBitWidth) * d; | ||
| 70 | x >>= (kuiScaleBitHeight - 1); | ||
| 71 | x += 1; | ||
| 72 | x >>= 1; | ||
| 73 | //x = (((__int64)(SCALE_BIG - 1 - iFu))*(SCALE_BIG - 1 - fv)*a + ((__int64)iFu)*(SCALE_BIG - 1 -fv)*b + ((__int64)(SCALE_BIG - 1 -iFu))*fv*c + | ||
| 74 | // ((__int64)iFu)*fv*d + (1 << (2*SCALE_BIT_BIG-1)) ) >> (2*SCALE_BIT_BIG); | ||
| 75 | x = WELS_CLAMP (x, 0, 255); | ||
| 76 | *pByDst++ = (uint8_t)x; | ||
| 77 | |||
| 78 | iXInverse += fScalex; | ||
| 79 | } | ||
| 80 | *pByDst = * (pBySrc + (iXInverse >> kuiScaleBitWidth)); | ||
| 81 | pByLineDst += kiDstStride; | ||
| 82 | iYInverse += fScaley; | ||
| 83 | } | ||
| 84 | |||
| 85 | // last row special | ||
| 86 | { | ||
| 87 | int32_t iYy = iYInverse >> kuiScaleBitHeight; | ||
| 88 | uint8_t* pBySrc = pSrc + iYy * kiSrcStride; | ||
| 89 | |||
| 90 | pByDst = pByLineDst; | ||
| 91 | iXInverse = 1 << (kuiScaleBitWidth - 1); | ||
| 92 | for (int32_t j = 0; j < kiDstWidth; j++) { | ||
| 93 | int32_t iXx = iXInverse >> kuiScaleBitWidth; | ||
| 94 | *pByDst++ = * (pBySrc + iXx); | ||
| 95 | |||
| 96 | iXInverse += fScalex; | ||
| 97 | } | ||
| 98 | } | ||
| 99 | } | ||
| 100 | |||
| 101 | void GeneralBilinearAccurateDownsampler_ref (uint8_t* pDst, const int32_t kiDstStride, const int32_t kiDstWidth, const int32_t kiDstHeight, | ||
| 102 | uint8_t* pSrc, const int32_t kiSrcStride, const int32_t kiSrcWidth, const int32_t kiSrcHeight) { | ||
| 103 | const int32_t kiScaleBit = 15; | ||
| 104 | const int32_t kiScale = (1 << kiScaleBit); | ||
| 105 | int32_t iScalex = WELS_ROUND ((float)kiSrcWidth / (float)kiDstWidth * kiScale); | ||
| 106 | int32_t iScaley = WELS_ROUND ((float)kiSrcHeight / (float)kiDstHeight * kiScale); | ||
| 107 | int64_t x; | ||
| 108 | int32_t iYInverse, iXInverse; | ||
| 109 | |||
| 110 | uint8_t* pByDst = pDst; | ||
| 111 | uint8_t* pByLineDst = pDst; | ||
| 112 | |||
| 113 | iYInverse = 1 << (kiScaleBit - 1); | ||
| 114 | for (int32_t i = 0; i < kiDstHeight - 1; i++) { | ||
| 115 | int32_t iYy = iYInverse >> kiScaleBit; | ||
| 116 | int32_t iFv = iYInverse & (kiScale - 1); | ||
| 117 | |||
| 118 | uint8_t* pBySrc = pSrc + iYy * kiSrcStride; | ||
| 119 | |||
| 120 | pByDst = pByLineDst; | ||
| 121 | iXInverse = 1 << (kiScaleBit - 1); | ||
| 122 | for (int32_t j = 0; j < kiDstWidth - 1; j++) { | ||
| 123 | int32_t iXx = iXInverse >> kiScaleBit; | ||
| 124 | int32_t iFu = iXInverse & (kiScale - 1); | ||
| 125 | |||
| 126 | uint8_t* pByCurrent = pBySrc + iXx; | ||
| 127 | uint8_t a, b, c, d; | ||
| 128 | |||
| 129 | a = *pByCurrent; | ||
| 130 | b = * (pByCurrent + 1); | ||
| 131 | c = * (pByCurrent + kiSrcStride); | ||
| 132 | d = * (pByCurrent + kiSrcStride + 1); | ||
| 133 | |||
| 134 | x = (((int64_t) (kiScale - 1 - iFu)) * (kiScale - 1 - iFv) * a + ((int64_t)iFu) * (kiScale - 1 - iFv) * b + ((int64_t) ( | ||
| 135 | kiScale - 1 - iFu)) * iFv * c + | ||
| 136 | ((int64_t)iFu) * iFv * d + (int64_t) (1 << (2 * kiScaleBit - 1))) >> (2 * kiScaleBit); | ||
| 137 | x = WELS_CLAMP (x, 0, 255); | ||
| 138 | *pByDst++ = (uint8_t)x; | ||
| 139 | |||
| 140 | iXInverse += iScalex; | ||
| 141 | } | ||
| 142 | *pByDst = * (pBySrc + (iXInverse >> kiScaleBit)); | ||
| 143 | pByLineDst += kiDstStride; | ||
| 144 | iYInverse += iScaley; | ||
| 145 | } | ||
| 146 | |||
| 147 | // last row special | ||
| 148 | { | ||
| 149 | int32_t iYy = iYInverse >> kiScaleBit; | ||
| 150 | uint8_t* pBySrc = pSrc + iYy * kiSrcStride; | ||
| 151 | |||
| 152 | pByDst = pByLineDst; | ||
| 153 | iXInverse = 1 << (kiScaleBit - 1); | ||
| 154 | for (int32_t j = 0; j < kiDstWidth; j++) { | ||
| 155 | int32_t iXx = iXInverse >> kiScaleBit; | ||
| 156 | *pByDst++ = * (pBySrc + iXx); | ||
| 157 | |||
| 158 | iXInverse += iScalex; | ||
| 159 | } | ||
| 160 | } | ||
| 161 | } | ||
| 162 | |||
| 163 | #define GENERATE_DyadicBilinearDownsampler_UT(func, ASM, CPUFLAGS) \ | ||
| 164 | TEST (DownSampleTest, func) { \ | ||
| 165 | if (ASM) {\ | ||
| 166 | int32_t iCpuCores = 0; \ | ||
| 167 | uint32_t m_uiCpuFeatureFlag = WelsCPUFeatureDetect (&iCpuCores); \ | ||
| 168 | if (0 == (m_uiCpuFeatureFlag & CPUFLAGS)) \ | ||
| 169 | return; \ | ||
| 170 | } \ | ||
| 171 | ENFORCE_STACK_ALIGN_1D (uint8_t, dst_c, 50000, 16); \ | ||
| 172 | ENFORCE_STACK_ALIGN_1D (uint8_t, src_c, 50000, 16); \ | ||
| 173 | int dst_stride_c; \ | ||
| 174 | int src_stride_c; \ | ||
| 175 | int src_width_c; \ | ||
| 176 | int src_height_c; \ | ||
| 177 | ENFORCE_STACK_ALIGN_1D (uint8_t, dst_a, 50000, 16); \ | ||
| 178 | ENFORCE_STACK_ALIGN_1D (uint8_t, src_a, 50000, 16); \ | ||
| 179 | int dst_stride_a; \ | ||
| 180 | int src_stride_a; \ | ||
| 181 | int src_width_a; \ | ||
| 182 | int src_height_a; \ | ||
| 183 | dst_stride_c = dst_stride_a = 560; \ | ||
| 184 | src_stride_c = src_stride_a = 560; \ | ||
| 185 | src_width_c = src_width_a = 512; \ | ||
| 186 | src_height_c = src_height_a = 80; \ | ||
| 187 | for (int j = 0; j < 50000; j++) { \ | ||
| 188 | dst_c[j] = dst_a[j] = rand() % 256; \ | ||
| 189 | src_c[j] = src_a[j] = rand() % 256; \ | ||
| 190 | } \ | ||
| 191 | DyadicBilinearDownsampler_ref (dst_c, dst_stride_c, src_c, src_stride_c, src_width_c, src_height_c); \ | ||
| 192 | func (dst_a, dst_stride_a, src_a, src_stride_a, src_width_a, src_height_a); \ | ||
| 193 | for (int j = 0; j < (src_height_c >> 1); j++) { \ | ||
| 194 | for (int m = 0; m < (src_width_c >> 1); m++) { \ | ||
| 195 | ASSERT_EQ (dst_c[m + j * dst_stride_c], dst_a[m + j * dst_stride_a]); \ | ||
| 196 | } \ | ||
| 197 | } \ | ||
| 198 | } | ||
| 199 | |||
| 200 | #define GENERATE_GeneralBilinearDownsampler_UT(func, ref, ASM, CPUFLAGS) \ | ||
| 201 | TEST (DownSampleTest, func) { \ | ||
| 202 | if (ASM) {\ | ||
| 203 | int32_t iCpuCores = 0; \ | ||
| 204 | uint32_t m_uiCpuFeatureFlag = WelsCPUFeatureDetect (&iCpuCores); \ | ||
| 205 | if (0 == (m_uiCpuFeatureFlag & CPUFLAGS)) \ | ||
| 206 | return; \ | ||
| 207 | } \ | ||
| 208 | ENFORCE_STACK_ALIGN_1D (uint8_t, dst_c, 70000, 16); \ | ||
| 209 | ENFORCE_STACK_ALIGN_1D (uint8_t, src_c, 70000, 16); \ | ||
| 210 | unsigned int dst_stride_c; \ | ||
| 211 | unsigned int dst_width_c; \ | ||
| 212 | unsigned int dst_height_c; \ | ||
| 213 | unsigned int src_stride_c; \ | ||
| 214 | unsigned int src_width_c; \ | ||
| 215 | unsigned int src_height_c; \ | ||
| 216 | ENFORCE_STACK_ALIGN_1D (uint8_t, dst_a, 70000, 16); \ | ||
| 217 | ENFORCE_STACK_ALIGN_1D (uint8_t, src_a, 70000, 16); \ | ||
| 218 | unsigned int dst_stride_a; \ | ||
| 219 | unsigned int dst_width_a; \ | ||
| 220 | unsigned int dst_height_a; \ | ||
| 221 | unsigned int src_stride_a; \ | ||
| 222 | unsigned int src_width_a; \ | ||
| 223 | unsigned int src_height_a; \ | ||
| 224 | dst_stride_c = dst_stride_a = 320; \ | ||
| 225 | src_stride_c = src_stride_a = 320; \ | ||
| 226 | src_width_c = src_width_a = 320; \ | ||
| 227 | src_height_c = src_height_a = 180; \ | ||
| 228 | dst_width_c = dst_width_a = 300; \ | ||
| 229 | dst_height_c = dst_height_a = 160; \ | ||
| 230 | for (int j = 0; j < 70000; j++) { \ | ||
| 231 | dst_c[j] = dst_a[j] = rand() % 256; \ | ||
| 232 | src_c[j] = src_a[j] = rand() % 256; \ | ||
| 233 | } \ | ||
| 234 | ref (dst_c, dst_stride_c, dst_width_c, dst_height_c, src_c, src_stride_c, src_width_c, src_height_c); \ | ||
| 235 | func (dst_a, dst_stride_a, dst_width_a, dst_height_a, src_a, src_stride_a, src_width_a, src_height_a); \ | ||
| 236 | for (int j = 0; j < dst_height_c; j++) { \ | ||
| 237 | for (int m = 0; m < dst_width_c ; m++) { \ | ||
| 238 | ASSERT_EQ (dst_c[m + j * dst_stride_c], dst_a[m + j * dst_stride_a]); \ | ||
| 239 | } \ | ||
| 240 | } \ | ||
| 241 | } | ||
| 242 | |||
| 243 | |||
| 244 | GENERATE_DyadicBilinearDownsampler_UT (DyadicBilinearDownsampler_c, 0, 0) | ||
| 245 | GENERATE_GeneralBilinearDownsampler_UT (GeneralBilinearFastDownsampler_c, GeneralBilinearFastDownsampler_ref, 0, 0) | ||
| 246 | GENERATE_GeneralBilinearDownsampler_UT (GeneralBilinearAccurateDownsampler_c, GeneralBilinearAccurateDownsampler_ref, 0, 0) | ||
| 247 | |||
| 248 | #if defined(X86_ASM) | ||
| 249 | GENERATE_DyadicBilinearDownsampler_UT (DyadicBilinearDownsamplerWidthx32_sse, 1, WELS_CPU_SSE) | ||
| 250 | GENERATE_DyadicBilinearDownsampler_UT (DyadicBilinearDownsamplerWidthx16_sse, 1, WELS_CPU_SSE) | ||
| 251 | GENERATE_DyadicBilinearDownsampler_UT (DyadicBilinearDownsamplerWidthx8_sse, 1, WELS_CPU_SSE) | ||
| 252 | |||
| 253 | GENERATE_DyadicBilinearDownsampler_UT (DyadicBilinearDownsamplerWidthx32_ssse3, 1, WELS_CPU_SSSE3) | ||
| 254 | GENERATE_DyadicBilinearDownsampler_UT (DyadicBilinearDownsamplerWidthx16_ssse3, 1, WELS_CPU_SSSE3) | ||
| 255 | |||
| 256 | GENERATE_DyadicBilinearDownsampler_UT (DyadicBilinearDownsamplerWidthx32_sse4, 1, WELS_CPU_SSE41) | ||
| 257 | GENERATE_DyadicBilinearDownsampler_UT (DyadicBilinearDownsamplerWidthx16_sse4, 1, WELS_CPU_SSE41) | ||
| 258 | |||
| 259 | GENERATE_GeneralBilinearDownsampler_UT (GeneralBilinearFastDownsamplerWrap_sse2, GeneralBilinearFastDownsampler_ref, 1, WELS_CPU_SSE2) | ||
| 260 | GENERATE_GeneralBilinearDownsampler_UT (GeneralBilinearAccurateDownsamplerWrap_sse2, GeneralBilinearAccurateDownsampler_ref, 1, WELS_CPU_SSE2) | ||
| 261 | #endif | ||
| 262 | |||
| 263 | #if defined(HAVE_NEON) | ||
| 264 | GENERATE_DyadicBilinearDownsampler_UT (DyadicBilinearDownsamplerWidthx32_neon, 1, WELS_CPU_NEON) | ||
| 265 | GENERATE_DyadicBilinearDownsampler_UT (DyadicBilinearDownsampler_neon, 1, WELS_CPU_NEON) | ||
| 266 | |||
| 267 | GENERATE_GeneralBilinearDownsampler_UT (GeneralBilinearAccurateDownsamplerWrap_neon, GeneralBilinearAccurateDownsampler_ref, 1, WELS_CPU_NEON) | ||
| 268 | #endif | ||
| 269 | |||
| 270 | #if defined(HAVE_NEON_AARCH64) | ||
| 271 | GENERATE_DyadicBilinearDownsampler_UT (DyadicBilinearDownsamplerWidthx32_AArch64_neon, 1, WELS_CPU_NEON) | ||
| 272 | GENERATE_DyadicBilinearDownsampler_UT (DyadicBilinearDownsampler_AArch64_neon, 1, WELS_CPU_NEON) | ||
| 273 | |||
| 274 | GENERATE_GeneralBilinearDownsampler_UT (GeneralBilinearAccurateDownsamplerWrap_AArch64_neon, GeneralBilinearAccurateDownsampler_ref, 1, WELS_CPU_NEON) | ||
| 275 | #endif | ||