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 | |