Showing the changes to codec/encoder/core/src/mc.cpp (1 of 308 files). Show all
Unified · Split
| @@ -0,0 +1,595 @@ | |||
| 1 | /*! | ||
| 2 | * \copy | ||
| 3 | * Copyright (c) 2009-2013, Cisco Systems | ||
| 4 | * All rights reserved. | ||
| 5 | * | ||
| 6 | * Redistribution and use in source and binary forms, with or without | ||
| 7 | * modification, are permitted provided that the following conditions | ||
| 8 | * are met: | ||
| 9 | * | ||
| 10 | * * Redistributions of source code must retain the above copyright | ||
| 11 | * notice, this list of conditions and the following disclaimer. | ||
| 12 | * | ||
| 13 | * * Redistributions in binary form must reproduce the above copyright | ||
| 14 | * notice, this list of conditions and the following disclaimer in | ||
| 15 | * the documentation and/or other materials provided with the | ||
| 16 | * distribution. | ||
| 17 | * | ||
| 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
| 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
| 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | ||
| 21 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | ||
| 22 | * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
| 23 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | ||
| 24 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
| 25 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | ||
| 26 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
| 27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN | ||
| 28 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
| 29 | * POSSIBILITY OF SUCH DAMAGE. | ||
| 30 | * | ||
| 31 | * | ||
| 32 | * \file mc.c | ||
| 33 | * | ||
| 34 | * \brief Interfaces implementation for motion compensation | ||
| 35 | * | ||
| 36 | * \date 03/17/2009 Created | ||
| 37 | * | ||
| 38 | ************************************************************************************* | ||
| 39 | */ | ||
| 40 | |||
| 41 | #include <string.h> | ||
| 42 | #include "as264_common.h" | ||
| 43 | #include "typedefs.h" | ||
| 44 | #include "wels_const.h" | ||
| 45 | #include "macros.h" | ||
| 46 | #include "mc.h" | ||
| 47 | #include "sample.h" | ||
| 48 | #include "cpu_core.h" | ||
| 49 | #include "array_stack_align.h" | ||
| 50 | |||
| 51 | namespace WelsSVCEnc { | ||
| 52 | /*------------------weight for chroma fraction pixel interpolation------------------*/ | ||
| 53 | //kuiA = (8 - dx) * (8 - dy); | ||
| 54 | //kuiB = dx * (8 - dy); | ||
| 55 | //kuiC = (8 - dx) * dy; | ||
| 56 | //kuiD = dx * dy | ||
| 57 | static const uint8_t g_kuiABCD[8][8][4] = ////g_kuiA[dy][dx], g_kuiB[dy][dx], g_kuiC[dy][dx], g_kuiD[dy][dx] | ||
| 58 | { | ||
| 59 | { | ||
| 60 | {64, 0, 0, 0},{56, 8, 0, 0},{48, 16, 0, 0},{40, 24, 0, 0}, | ||
| 61 | {32, 32, 0, 0},{24, 40, 0, 0},{16, 48, 0, 0},{8, 56, 0, 0} | ||
| 62 | }, | ||
| 63 | { | ||
| 64 | {56, 0, 8, 0},{49, 7, 7, 1},{42, 14, 6, 2},{35, 21, 5, 3}, | ||
| 65 | {28, 28, 4, 4},{21, 35, 3, 5},{14, 42, 2, 6},{7, 49, 1, 7} | ||
| 66 | }, | ||
| 67 | { | ||
| 68 | {48, 0, 16, 0},{42, 6, 14, 2},{36, 12, 12, 4},{30, 18, 10, 6}, | ||
| 69 | {24, 24, 8, 8},{18, 30, 6, 10},{12, 36, 4, 12},{6, 42, 2, 14} | ||
| 70 | }, | ||
| 71 | { | ||
| 72 | {40, 0, 24, 0},{35, 5, 21, 3},{30, 10, 18, 6},{25, 15, 15, 9}, | ||
| 73 | {20, 20, 12, 12},{15, 25, 9, 15},{10, 30, 6, 18},{5, 35, 3, 21} | ||
| 74 | }, | ||
| 75 | { | ||
| 76 | {32, 0, 32, 0},{28, 4, 28, 4},{24, 8, 24, 8},{20, 12, 20, 12}, | ||
| 77 | {16, 16, 16, 16},{12, 20, 12, 20},{8, 24, 8, 24},{4, 28, 4, 28} | ||
| 78 | }, | ||
| 79 | { | ||
| 80 | {24, 0, 40, 0},{21, 3, 35, 5},{18, 6, 30, 10},{15, 9, 25, 15}, | ||
| 81 | {12, 12, 20, 20},{9, 15, 15, 25},{6, 18, 10, 30},{3, 21, 5, 35} | ||
| 82 | }, | ||
| 83 | { | ||
| 84 | {16, 0, 48, 0},{14, 2, 42, 6},{12, 4, 36, 12},{10, 6, 30, 18}, | ||
| 85 | {8, 8, 24, 24},{6, 10, 18, 30},{4, 12, 12, 36},{2, 14, 6, 42} | ||
| 86 | }, | ||
| 87 | { | ||
| 88 | {8, 0, 56, 0},{7, 1, 49, 7},{6, 2, 42, 14},{5, 3, 35, 21}, | ||
| 89 | {4, 4, 28, 28},{3, 5, 21, 35},{2, 6, 14, 42},{1, 7, 7, 49} | ||
| 90 | } | ||
| 91 | }; | ||
| 92 | typedef int32_t (*VerFilterFunc)(uint8_t* pSrc, const int32_t kiSrcStride); | ||
| 93 | typedef int32_t (*HorFilterFunc)(uint8_t* pSrc); | ||
| 94 | typedef int32_t (*HorFilterFuncInput16Bits)(int16_t* pSrc); | ||
| 95 | |||
| 96 | VerFilterFunc fpVerFilter = NULL; | ||
| 97 | HorFilterFunc fpHorFilter = NULL; | ||
| 98 | HorFilterFuncInput16Bits fpHorFilterInput16Bits = NULL; | ||
| 99 | |||
| 100 | typedef void (*WelsMcFunc0) (uint8_t* pSrc, int32_t iSrcStride, uint8_t* pDst, int32_t iDstStride,int32_t iHeight); | ||
| 101 | typedef void (*WelsMcFunc1) (uint8_t* pDst, int32_t iDstStride, uint8_t* psrcA, int32_t iSrcAStride, uint8_t* pSrcB, int32_t iSrcBStride, int32_t iHeight); | ||
| 102 | WelsMcFunc0 McCopyWidthEq16 = NULL; | ||
| 103 | WelsMcFunc0 McCopyWidthEq8 = NULL; | ||
| 104 | WelsMcFunc0 McCopyWidthEq4 = NULL; | ||
| 105 | WelsMcFunc0 pfMcHorVer02WidthEq16 = NULL; | ||
| 106 | WelsMcFunc1 pfPixelAvgWidthEq16 = NULL; | ||
| 107 | WelsMcFunc0 pfMcHorVer20WidthEq16 = NULL; | ||
| 108 | WelsMcFunc0 pfMcHorVer22WidthEq16 = NULL; | ||
| 109 | |||
| 110 | //***************************************************************************// | ||
| 111 | // C code implementation // | ||
| 112 | //***************************************************************************// | ||
| 113 | static inline void McCopyWidthEq4_c(uint8_t* pSrc, int32_t iSrcStride, uint8_t* pDst, int32_t iDstStride, int32_t iHeight) | ||
| 114 | { | ||
| 115 | int32_t i; | ||
| 116 | for (i = 0; i < iHeight; i++) | ||
| 117 | { | ||
| 118 | memcpy(pDst, pSrc, 4); // confirmed_safe_unsafe_usage | ||
| 119 | pDst += iDstStride; | ||
| 120 | pSrc += iSrcStride; | ||
| 121 | } | ||
| 122 | } | ||
| 123 | |||
| 124 | static inline void McCopyWidthEq8_c(uint8_t* pSrc, int32_t iSrcStride, uint8_t* pDst, int32_t iDstStride, int32_t iHeight) | ||
| 125 | |||
| 126 | { | ||
| 127 | int32_t i; | ||
| 128 | for (i = 0; i < iHeight; i++) | ||
| 129 | { | ||
| 130 | memcpy(pDst, pSrc, 8); // confirmed_safe_unsafe_usage | ||
| 131 | pDst += iDstStride; | ||
| 132 | pSrc += iSrcStride; | ||
| 133 | } | ||
| 134 | } | ||
| 135 | static inline void McCopyWidthEq16_c(uint8_t* pSrc, int32_t iSrcStride, uint8_t* pDst, int32_t iDstStride, int32_t iHeight) | ||
| 136 | { | ||
| 137 | int32_t i; | ||
| 138 | for (i = 0; i < iHeight; i++) | ||
| 139 | { | ||
| 140 | memcpy(pDst, pSrc, 16); // confirmed_safe_unsafe_usage | ||
| 141 | pDst += iDstStride; | ||
| 142 | pSrc += iSrcStride; | ||
| 143 | } | ||
| 144 | } | ||
| 145 | |||
| 146 | //--------------------Luma sample MC------------------// | ||
| 147 | static inline int32_t HorFilter_c(uint8_t* pSrc) | ||
| 148 | { | ||
| 149 | int32_t iPix05 = pSrc[-2] + pSrc[3]; | ||
| 150 | int32_t iPix14 = pSrc[-1] + pSrc[2]; | ||
| 151 | int32_t iPix23 = pSrc[ 0] + pSrc[1]; | ||
| 152 | |||
| 153 | return (iPix05 - ((iPix14<<2)+iPix14) + (iPix23<<4) + (iPix23<<2)); | ||
| 154 | } | ||
| 155 | |||
| 156 | static inline int32_t HorFilterInput16bit1_c(int16_t* pSrc) | ||
| 157 | { | ||
| 158 | int32_t iPix05 = pSrc[-2] + pSrc[3]; | ||
| 159 | int32_t iPix14 = pSrc[-1] + pSrc[2]; | ||
| 160 | int32_t iPix23 = pSrc[ 0] + pSrc[1]; | ||
| 161 | |||
| 162 | return (iPix05 - ((iPix14<<2)+iPix14) + (iPix23<<4) + (iPix23<<2)); | ||
| 163 | } | ||
| 164 | static inline int32_t VerFilter_c(uint8_t* pSrc, const int32_t kiSrcStride) | ||
| 165 | { | ||
| 166 | const int32_t kiLine1 = kiSrcStride; | ||
| 167 | const int32_t kiLine2 = (kiSrcStride<<1); | ||
| 168 | const int32_t kiLine3 = kiLine1 + kiLine2; | ||
| 169 | const uint32_t kuiPix05= *(pSrc - kiLine2) + *(pSrc + kiLine3); | ||
| 170 | const uint32_t kuiPix14= *(pSrc - kiLine1) + *(pSrc + kiLine2); | ||
| 171 | const uint32_t kuiPix23= *(pSrc ) + *(pSrc + kiLine1); | ||
| 172 | |||
| 173 | return (kuiPix05 - ((kuiPix14<<2)+kuiPix14) + (kuiPix23<<4) + (kuiPix23<<2)); | ||
| 174 | } | ||
| 175 | |||
| 176 | static inline void PixelAvgWidthEq8_c(uint8_t* pDst, int32_t iDstStride, uint8_t* pSrcA, int32_t iSrcAStride, | ||
| 177 | uint8_t* pSrcB, int32_t iSrcBStride, int32_t iHeight) | ||
| 178 | { | ||
| 179 | int32_t i, j; | ||
| 180 | for (i = 0; i < iHeight; i++) | ||
| 181 | { | ||
| 182 | for (j = 0; j < 8; j++) | ||
| 183 | { | ||
| 184 | pDst[j] = (pSrcA[j] + pSrcB[j] + 1) >> 1; | ||
| 185 | } | ||
| 186 | pDst += iDstStride; | ||
| 187 | pSrcA += iSrcAStride; | ||
| 188 | pSrcB += iSrcBStride; | ||
| 189 | } | ||
| 190 | } | ||
| 191 | static inline void PixelAvgWidthEq16_c(uint8_t* pDst, int32_t iDstStride, uint8_t* pSrcA, int32_t iSrcAStride, | ||
| 192 | uint8_t* pSrcB, int32_t iSrcBStride, int32_t iHeight) | ||
| 193 | { | ||
| 194 | int32_t i, j; | ||
| 195 | for (i = 0; i < iHeight; i++) | ||
| 196 | { | ||
| 197 | for (j = 0; j < 16; j++) | ||
| 198 | { | ||
| 199 | pDst[j] = (pSrcA[j] + pSrcB[j] + 1) >> 1; | ||
| 200 | } | ||
| 201 | pDst += iDstStride; | ||
| 202 | pSrcA += iSrcAStride; | ||
| 203 | pSrcB += iSrcBStride; | ||
| 204 | } | ||
| 205 | } | ||
| 206 | |||
| 207 | //horizontal filter to gain half sample, that is (2, 0) location in quarter sample | ||
| 208 | static inline void McHorVer20WidthEq16_c(uint8_t* pSrc, int32_t iSrcStride, uint8_t* pDst, int32_t iDstStride, int32_t iHeight) | ||
| 209 | { | ||
| 210 | int32_t i, j; | ||
| 211 | for (i = 0; i < iHeight; i++) | ||
| 212 | { | ||
| 213 | for (j = 0; j < 16; j++) | ||
| 214 | { | ||
| 215 | pDst[j] = WELS_CLIP1((fpHorFilter(pSrc+j)+16)>>5); | ||
| 216 | } | ||
| 217 | pDst += iDstStride; | ||
| 218 | pSrc += iSrcStride; | ||
| 219 | } | ||
| 220 | } | ||
| 221 | //vertical filter to gain half sample, that is (0, 2) location in quarter sample | ||
| 222 | static inline void McHorVer02WidthEq16_c(uint8_t* pSrc, int32_t iSrcStride, uint8_t* pDst, int32_t iDstStride, int32_t iHeight) | ||
| 223 | { | ||
| 224 | int32_t i, j; | ||
| 225 | for (i = 0; i < iHeight; i++) | ||
| 226 | { | ||
| 227 | for (j = 0; j < 16; j++) | ||
| 228 | { | ||
| 229 | pDst[j] = WELS_CLIP1((fpVerFilter(pSrc+j, iSrcStride)+16)>>5); | ||
| 230 | } | ||
| 231 | pDst += iDstStride; | ||
| 232 | pSrc += iSrcStride; | ||
| 233 | } | ||
| 234 | } | ||
| 235 | //horizontal and vertical filter to gain half sample, that is (2, 2) location in quarter sample | ||
| 236 | static inline void McHorVer22WidthEq16_c(uint8_t* pSrc, int32_t iSrcStride, uint8_t* pDst, int32_t iDstStride, int32_t iHeight) | ||
| 237 | { | ||
| 238 | int16_t pTmp[16+5] = {0}; //16 | ||
| 239 | int32_t i, j, k; | ||
| 240 | |||
| 241 | for (i = 0; i < iHeight; i++) | ||
| 242 | { | ||
| 243 | for (j = 0; j < 16 + 5; j++) | ||
| 244 | { | ||
| 245 | pTmp[j] = fpVerFilter(pSrc-2+j, iSrcStride); | ||
| 246 | } | ||
| 247 | for (k = 0; k < 16; k++) | ||
| 248 | { | ||
| 249 | pDst[k] = WELS_CLIP1((fpHorFilterInput16Bits(&pTmp[2+k])+512)>>10); | ||
| 250 | } | ||
| 251 | pSrc += iSrcStride; | ||
| 252 | pDst += iDstStride; | ||
| 253 | } | ||
| 254 | } | ||
| 255 | |||
| 256 | /////////////////////luma MC////////////////////////// | ||
| 257 | |||
| 258 | static inline void McHorVer01WidthEq16(uint8_t* pSrc, int32_t iSrcStride, uint8_t* pDst, int32_t iDstStride, int32_t iHeight) | ||
| 259 | { | ||
| 260 | ENFORCE_STACK_ALIGN_1D(uint8_t, pTmp, 256, 16) | ||
| 261 | |||
| 262 | pfMcHorVer02WidthEq16(pSrc, iSrcStride, pTmp, 16, iHeight); | ||
| 263 | pfPixelAvgWidthEq16(pDst, iDstStride, pSrc, iSrcStride, pTmp, 16,iHeight); | ||
| 264 | } | ||
| 265 | static inline void McHorVer03WidthEq16(uint8_t* pSrc, int32_t iSrcStride, uint8_t* pDst, int32_t iDstStride, int32_t iHeight) | ||
| 266 | { | ||
| 267 | ENFORCE_STACK_ALIGN_1D(uint8_t, pTmp, 256, 16) | ||
| 268 | |||
| 269 | pfMcHorVer02WidthEq16(pSrc, iSrcStride, pTmp, 16, iHeight); | ||
| 270 | pfPixelAvgWidthEq16(pDst, iDstStride, pSrc+iSrcStride, iSrcStride, pTmp, 16,iHeight); | ||
| 271 | } | ||
| 272 | static inline void McHorVer10WidthEq16(uint8_t* pSrc, int32_t iSrcStride, uint8_t* pDst, int32_t iDstStride, int32_t iHeight) | ||
| 273 | { | ||
| 274 | ENFORCE_STACK_ALIGN_1D(uint8_t, pTmp, 256, 16) | ||
| 275 | |||
| 276 | pfMcHorVer20WidthEq16(pSrc, iSrcStride, pTmp, 16, iHeight); | ||
| 277 | pfPixelAvgWidthEq16(pDst, iDstStride, pSrc, iSrcStride, pTmp, 16,iHeight); | ||
| 278 | } | ||
| 279 | static inline void McHorVer11WidthEq16(uint8_t* pSrc, int32_t iSrcStride, uint8_t* pDst, int32_t iDstStride, int32_t iHeight) | ||
| 280 | { | ||
| 281 | ENFORCE_STACK_ALIGN_1D(uint8_t, pTmp, 512, 16) | ||
| 282 | |||
| 283 | pfMcHorVer20WidthEq16(pSrc, iSrcStride, pTmp, 16, iHeight); | ||
| 284 | pfMcHorVer02WidthEq16(pSrc, iSrcStride, &pTmp[256], 16,iHeight); | ||
| 285 | pfPixelAvgWidthEq16(pDst, iDstStride, pTmp, 16, &pTmp[256], 16,iHeight); | ||
| 286 | } | ||
| 287 | static inline void McHorVer12WidthEq16(uint8_t* pSrc, int32_t iSrcStride, uint8_t* pDst, int32_t iDstStride, int32_t iHeight) | ||
| 288 | { | ||
| 289 | ENFORCE_STACK_ALIGN_1D(uint8_t, pTmp, 512, 16) | ||
| 290 | |||
| 291 | pfMcHorVer02WidthEq16(pSrc, iSrcStride, pTmp, 16,iHeight); | ||
| 292 | pfMcHorVer22WidthEq16(pSrc, iSrcStride, &pTmp[256], 16,iHeight); | ||
| 293 | pfPixelAvgWidthEq16(pDst, iDstStride, pTmp, 16, &pTmp[256], 16,iHeight); | ||
| 294 | } | ||
| 295 | static inline void McHorVer13WidthEq16(uint8_t* pSrc, int32_t iSrcStride, uint8_t* pDst, int32_t iDstStride, int32_t iHeight) | ||
| 296 | { | ||
| 297 | ENFORCE_STACK_ALIGN_1D(uint8_t, pTmp, 512, 16) | ||
| 298 | |||
| 299 | pfMcHorVer20WidthEq16(pSrc+iSrcStride, iSrcStride, pTmp, 16,iHeight); | ||
| 300 | pfMcHorVer02WidthEq16(pSrc, iSrcStride, &pTmp[256], 16,iHeight); | ||
| 301 | pfPixelAvgWidthEq16(pDst, iDstStride, pTmp, 16, &pTmp[256], 16,iHeight); | ||
| 302 | } | ||
| 303 | static inline void McHorVer21WidthEq16(uint8_t* pSrc, int32_t iSrcStride, uint8_t* pDst, int32_t iDstStride, int32_t iHeight) | ||
| 304 | { | ||
| 305 | ENFORCE_STACK_ALIGN_1D(uint8_t, pTmp, 512, 16) | ||
| 306 | |||
| 307 | pfMcHorVer20WidthEq16(pSrc, iSrcStride, pTmp, 16,iHeight); | ||
| 308 | pfMcHorVer22WidthEq16(pSrc, iSrcStride, &pTmp[256], 16, iHeight); | ||
| 309 | pfPixelAvgWidthEq16(pDst, iDstStride,pTmp, 16, &pTmp[256], 16,iHeight); | ||
| 310 | } | ||
| 311 | static inline void McHorVer23WidthEq16(uint8_t* pSrc, int32_t iSrcStride, uint8_t* pDst, int32_t iDstStride, int32_t iHeight) | ||
| 312 | { | ||
| 313 | ENFORCE_STACK_ALIGN_1D(uint8_t, pTmp, 512, 16) | ||
| 314 | |||
| 315 | pfMcHorVer20WidthEq16(pSrc+iSrcStride, iSrcStride, pTmp, 16,iHeight); | ||
| 316 | pfMcHorVer22WidthEq16(pSrc, iSrcStride, &pTmp[256], 16,iHeight); | ||
| 317 | pfPixelAvgWidthEq16(pDst, iDstStride, pTmp, 16, &pTmp[256], 16,iHeight); | ||
| 318 | } | ||
| 319 | static inline void McHorVer30WidthEq16(uint8_t* pSrc, int32_t iSrcStride, uint8_t* pDst, int32_t iDstStride, int32_t iHeight) | ||
| 320 | { | ||
| 321 | ENFORCE_STACK_ALIGN_1D(uint8_t, pTmp, 256, 16) | ||
| 322 | |||
| 323 | pfMcHorVer20WidthEq16(pSrc, iSrcStride, pTmp, 16,iHeight); | ||
| 324 | pfPixelAvgWidthEq16(pDst, iDstStride, pSrc+1, iSrcStride, pTmp, 16,iHeight); | ||
| 325 | } | ||
| 326 | static inline void McHorVer31WidthEq16(uint8_t* pSrc, int32_t iSrcStride, uint8_t* pDst, int32_t iDstStride, int32_t iHeight) | ||
| 327 | { | ||
| 328 | ENFORCE_STACK_ALIGN_1D(uint8_t, pTmp, 512, 16) | ||
| 329 | |||
| 330 | pfMcHorVer20WidthEq16(pSrc, iSrcStride, pTmp, 16,iHeight); | ||
| 331 | pfMcHorVer02WidthEq16(pSrc+1, iSrcStride, &pTmp[256], 16,iHeight); | ||
| 332 | pfPixelAvgWidthEq16(pDst, iDstStride, pTmp, 16, &pTmp[256], 16,iHeight); | ||
| 333 | } | ||
| 334 | static inline void McHorVer32WidthEq16(uint8_t* pSrc, int32_t iSrcStride, uint8_t* pDst, int32_t iDstStride, int32_t iHeight) | ||
| 335 | { | ||
| 336 | ENFORCE_STACK_ALIGN_1D(uint8_t, pTmp, 512, 16) | ||
| 337 | |||
| 338 | pfMcHorVer02WidthEq16(pSrc+1, iSrcStride, pTmp, 16,iHeight); | ||
| 339 | pfMcHorVer22WidthEq16(pSrc, iSrcStride, &pTmp[256], 16,iHeight); | ||
| 340 | pfPixelAvgWidthEq16(pDst, iDstStride, pTmp, 16, &pTmp[256], 16,iHeight); | ||
| 341 | } | ||
| 342 | static inline void McHorVer33WidthEq16(uint8_t* pSrc, int32_t iSrcStride, uint8_t* pDst, int32_t iDstStride, int32_t iHeight) | ||
| 343 | { | ||
| 344 | ENFORCE_STACK_ALIGN_1D(uint8_t, pTmp, 512, 16) | ||
| 345 | |||
| 346 | pfMcHorVer20WidthEq16(pSrc+iSrcStride, iSrcStride, pTmp, 16,iHeight); | ||
| 347 | pfMcHorVer02WidthEq16(pSrc+1, iSrcStride, &pTmp[256], 16,iHeight); | ||
| 348 | pfPixelAvgWidthEq16(pDst, iDstStride, pTmp, 16, &pTmp[256], 16,iHeight); | ||
| 349 | } | ||
| 350 | |||
| 351 | static inline void McHorVer20_c(uint8_t* pSrc, int32_t iSrcStride, uint8_t* pDst, int32_t iDstStride, int32_t iWidth, int32_t iHeight) | ||
| 352 | { | ||
| 353 | int32_t i, j; | ||
| 354 | for (i = 0; i < iHeight; i++) | ||
| 355 | { | ||
| 356 | for (j = 0; j < iWidth; j++) | ||
| 357 | { | ||
| 358 | pDst[j] = WELS_CLIP1((fpHorFilter(pSrc+j)+16)>>5); | ||
| 359 | } | ||
| 360 | pDst += iDstStride; | ||
| 361 | pSrc += iSrcStride; | ||
| 362 | } | ||
| 363 | } | ||
| 364 | //vertical filter to gain half sample, that is (0, 2) location in quarter sample | ||
| 365 | static inline void McHorVer02_c(uint8_t* pSrc, int32_t iSrcStride, uint8_t* pDst, int32_t iDstStride, int32_t iWidth, int32_t iHeight) | ||
| 366 | { | ||
| 367 | int32_t i, j; | ||
| 368 | for (i = 0; i < iHeight; i++) | ||
| 369 | { | ||
| 370 | for (j = 0; j < iWidth; j++) | ||
| 371 | { | ||
| 372 | pDst[j] = WELS_CLIP1((fpVerFilter(pSrc+j, iSrcStride)+16)>>5); | ||
| 373 | } | ||
| 374 | pDst += iDstStride; | ||
| 375 | pSrc += iSrcStride; | ||
| 376 | } | ||
| 377 | } | ||
| 378 | //horizontal and vertical filter to gain half sample, that is (2, 2) location in quarter sample | ||
| 379 | static inline void McHorVer22_c(uint8_t* pSrc, int32_t iSrcStride, uint8_t* pDst, int32_t iDstStride, int32_t iWidth, int32_t iHeight) | ||
| 380 | { | ||
| 381 | int16_t pTmp[17+5] = {0}; //w+1 | ||
| 382 | int32_t i, j, k; | ||
| 383 | |||
| 384 | for (i = 0; i < iHeight; i++) | ||
| 385 | { | ||
| 386 | for (j = 0; j < iWidth + 5; j++) | ||
| 387 | { | ||
| 388 | pTmp[j] = fpVerFilter(pSrc-2+j, iSrcStride); | ||
| 389 | } | ||
| 390 | for (k = 0; k < iWidth; k++) | ||
| 391 | { | ||
| 392 | pDst[k] = WELS_CLIP1((fpHorFilterInput16Bits(&pTmp[2+k])+512)>>10); | ||
| 393 | } | ||
| 394 | pSrc += iSrcStride; | ||
| 395 | pDst += iDstStride; | ||
| 396 | } | ||
| 397 | } | ||
| 398 | static inline void McCopy(uint8_t* pSrc, int32_t iSrcStride, uint8_t* pDst, int32_t iDstStride, int32_t iWidth, int32_t iHeight) | ||
| 399 | { | ||
| 400 | int32_t i; | ||
| 401 | if (iWidth == 16 && McCopyWidthEq16!= NULL) | ||
| 402 | McCopyWidthEq16(pSrc,iSrcStride,pDst,iDstStride,iHeight); | ||
| 403 | else if(iWidth == 8 &&McCopyWidthEq8!= NULL) | ||
| 404 | McCopyWidthEq8(pSrc,iSrcStride,pDst,iDstStride,iHeight); | ||
| 405 | else if(iWidth == 4 &&McCopyWidthEq4!= NULL) | ||
| 406 | McCopyWidthEq4(pSrc,iSrcStride,pDst,iDstStride,iHeight); | ||
| 407 | else | ||
| 408 | { | ||
| 409 | for (i = 0; i < iHeight; i++) | ||
| 410 | { | ||
| 411 | memcpy(pDst, pSrc, iWidth); // confirmed_safe_unsafe_usage | ||
| 412 | pDst += iDstStride; | ||
| 413 | pSrc += iSrcStride; | ||
| 414 | } | ||
| 415 | } | ||
| 416 | } | ||
| 417 | |||
| 418 | void McChroma_c(uint8_t* pSrc, int32_t iSrcStride, uint8_t* pDst, int32_t iDstStride, | ||
| 419 | SMVUnitXY mv, int32_t iWidth, int32_t iHeight) | ||
| 420 | //pSrc has been added the offset of mv | ||
| 421 | { | ||
| 422 | const int32_t kiDx = mv.iMvX & 0x07; | ||
| 423 | const int32_t kiDy = mv.iMvY & 0x07; | ||
| 424 | |||
| 425 | if ( 0 == kiDx && 0 == kiDy ) | ||
| 426 | { | ||
| 427 | McCopy(pSrc, iSrcStride, pDst, iDstStride, iWidth, iHeight); | ||
| 428 | } | ||
| 429 | else | ||
| 430 | { | ||
| 431 | const int32_t kiDA = g_kuiABCD[kiDy][kiDx][0]; | ||
| 432 | const int32_t kiDB = g_kuiABCD[kiDy][kiDx][1]; | ||
| 433 | const int32_t kiDC = g_kuiABCD[kiDy][kiDx][2]; | ||
| 434 | const int32_t kiDD = g_kuiABCD[kiDy][kiDx][3]; | ||
| 435 | |||
| 436 | int32_t i, j; | ||
| 437 | |||
| 438 | uint8_t* pSrcNext = pSrc + iSrcStride; | ||
| 439 | |||
| 440 | for (i = 0; i < iHeight; i++) | ||
| 441 | { | ||
| 442 | for (j = 0; j < iWidth; j++) | ||
| 443 | { | ||
| 444 | pDst[j] = (kiDA * pSrc[j] + kiDB * pSrc[j+1] + kiDC * pSrcNext[j] + kiDD * pSrcNext[j+1] + 32) >> 6; | ||
| 445 | } | ||
| 446 | pDst += iDstStride; | ||
| 447 | pSrc = pSrcNext; | ||
| 448 | pSrcNext += iSrcStride; | ||
| 449 | } | ||
| 450 | } | ||
| 451 | } | ||
| 452 | //***************************************************************************// | ||
| 453 | // MMXEXT and SSE2 implementation // | ||
| 454 | //***************************************************************************// | ||
| 455 | #if defined(X86_ASM) | ||
| 456 | |||
| 457 | static inline void McHorVer22WidthEq8_sse2 ( uint8_t *pSrc, int32_t iSrcStride, uint8_t *pDst, int32_t iDstStride, int32_t iHeight ) | ||
| 458 | { | ||
| 459 | ENFORCE_STACK_ALIGN_2D(int16_t, pTap, 21, 8, 16) | ||
| 460 | McHorVer22Width8HorFirst_sse2(pSrc-2, iSrcStride, (uint8_t *)pTap,16,iHeight+5); | ||
| 461 | McHorVer22VerLastAlign_sse2((uint8_t *)pTap,16, pDst, iDstStride, 8, iHeight); | ||
| 462 | } | ||
| 463 | |||
| 464 | //2010.2.5 | ||
| 465 | |||
| 466 | static inline void McHorVer02WidthEq16_sse2( uint8_t *pSrc, int32_t iSrcStride, uint8_t *PDst, int32_t iDstStride, int32_t iHeight ) | ||
| 467 | { | ||
| 468 | McHorVer02WidthEq8_sse2( pSrc, iSrcStride, PDst, iDstStride, iHeight ); | ||
| 469 | McHorVer02WidthEq8_sse2( &pSrc[8], iSrcStride, &PDst[8], iDstStride, iHeight ); | ||
| 470 | } | ||
| 471 | static inline void McHorVer22WidthEq16_sse2( uint8_t *pSrc, int32_t iSrcStride, uint8_t *pDst, int32_t iDstStride, int32_t iHeight ) | ||
| 472 | { | ||
| 473 | McHorVer22WidthEq8_sse2( pSrc, iSrcStride, pDst, iDstStride, iHeight ); | ||
| 474 | McHorVer22WidthEq8_sse2( &pSrc[8], iSrcStride, &pDst[8], iDstStride, iHeight ); | ||
| 475 | } | ||
| 476 | void McHorVer22_sse2( uint8_t *pSrc, int32_t iSrcStride, uint8_t *pDst, int32_t iDstStride, int32_t iWidth,int32_t iHeight ) | ||
| 477 | { | ||
| 478 | ENFORCE_STACK_ALIGN_2D(int16_t, pTap, 22, 24, 16) | ||
| 479 | int32_t tmp1 = 2*(iWidth-8); | ||
| 480 | McHorVer22HorFirst_sse2(pSrc-2, iSrcStride, (uint8_t *)pTap,48,iWidth,iHeight+5); | ||
| 481 | McHorVer22VerLastAlign_sse2((uint8_t *)pTap, 48, pDst, iDstStride, iWidth-1, iHeight); | ||
| 482 | McHorVer22VerLastUnAlign_sse2((uint8_t *)pTap+tmp1, 48, pDst+iWidth-8, iDstStride, 8, iHeight); | ||
| 483 | } | ||
| 484 | |||
| 485 | typedef void (*McChromaWidthEqx)(uint8_t *pSrc, int32_t iSrcStride, uint8_t *pDst, int32_t iDstStride, const uint8_t *pABCD,int32_t iHeigh); | ||
| 486 | void McChroma_sse2( uint8_t *pSrc, int32_t iSrcStride, uint8_t *pDst, int32_t iDstStride, | ||
| 487 | SMVUnitXY sMv, int32_t iWidth, int32_t iHeight ) | ||
| 488 | { | ||
| 489 | const int32_t kiD8x = sMv.iMvX&0x07; | ||
| 490 | const int32_t kiD8y = sMv.iMvY&0x07; | ||
| 491 | static const McChromaWidthEqx kpfFuncs[2] = | ||
| 492 | { | ||
| 493 | McChromaWidthEq4_mmx, | ||
| 494 | McChromaWidthEq8_sse2 | ||
| 495 | }; | ||
| 496 | |||
| 497 | if (0 == kiD8x && 0 == kiD8y) | ||
| 498 | { | ||
| 499 | McCopy(pSrc, iSrcStride, pDst, iDstStride, iWidth, iHeight); | ||
| 500 | } | ||
| 501 | else | ||
| 502 | { | ||
| 503 | kpfFuncs[(iWidth>>3)](pSrc, iSrcStride, pDst, iDstStride, g_kuiABCD[kiD8y][kiD8x], iHeight); | ||
| 504 | } | ||
| 505 | } | ||
| 506 | |||
| 507 | void McChroma_ssse3( uint8_t *pSrc, int32_t iSrcStride, uint8_t *pDst, int32_t iDstStride, | ||
| 508 | SMVUnitXY sMv, int32_t iWidth, int32_t iHeight ) | ||
| 509 | { | ||
| 510 | const int32_t kiD8x = sMv.iMvX&0x07; | ||
| 511 | const int32_t kiD8y = sMv.iMvY&0x07; | ||
| 512 | |||
| 513 | static const McChromaWidthEqx kpfFuncs[2] = | ||
| 514 | { | ||
| 515 | McChromaWidthEq4_mmx, | ||
| 516 | McChromaWidthEq8_ssse3 | ||
| 517 | }; | ||
| 518 | if (0 == kiD8x && 0 == kiD8y) | ||
| 519 | { | ||
| 520 | McCopy(pSrc, iSrcStride, pDst, iDstStride, iWidth, iHeight); | ||
| 521 | } | ||
| 522 | else | ||
| 523 | { | ||
| 524 | kpfFuncs[(iWidth>>3)](pSrc, iSrcStride, pDst, iDstStride, g_kuiABCD[kiD8y][kiD8x], iHeight); | ||
| 525 | } | ||
| 526 | |||
| 527 | } | ||
| 528 | |||
| 529 | #endif //X86_ASM | ||
| 530 | typedef void (*PixelAvgFunc) ( uint8_t *, int32_t, uint8_t *, int32_t, uint8_t *, int32_t, int32_t ); | ||
| 531 | void WelsInitMcFuncs( SWelsFuncPtrList *pFuncList, uint32_t uiCpuFlag ) | ||
| 532 | { | ||
| 533 | static PixelAvgFunc pfPixAvgFunc[2] ={PixelAvgWidthEq8_c,PixelAvgWidthEq16_c}; | ||
| 534 | |||
| 535 | static PWelsLumaQuarpelMcFunc pWelsMcFuncWidthEq16[16] = //[y*4+x] | ||
| 536 | { | ||
| 537 | McCopyWidthEq16_c, McHorVer10WidthEq16, McHorVer20WidthEq16_c, McHorVer30WidthEq16, | ||
| 538 | McHorVer01WidthEq16, McHorVer11WidthEq16, McHorVer21WidthEq16, McHorVer31WidthEq16, | ||
| 539 | McHorVer02WidthEq16_c, McHorVer12WidthEq16, McHorVer22WidthEq16_c, McHorVer32WidthEq16, | ||
| 540 | McHorVer03WidthEq16, McHorVer13WidthEq16, McHorVer23WidthEq16, McHorVer33WidthEq16 | ||
| 541 | }; | ||
| 542 | #if defined (X86_ASM) | ||
| 543 | static PWelsLumaQuarpelMcFunc pWelsMcFuncWidthEq16_sse2[16] = | ||
| 544 | { | ||
| 545 | McCopyWidthEq16_sse2, McHorVer10WidthEq16, McHorVer20WidthEq16_sse2, McHorVer30WidthEq16, | ||
| 546 | McHorVer01WidthEq16, McHorVer11WidthEq16, McHorVer21WidthEq16, McHorVer31WidthEq16, | ||
| 547 | McHorVer02WidthEq16_sse2, McHorVer12WidthEq16, McHorVer22WidthEq16_sse2, McHorVer32WidthEq16, | ||
| 548 | McHorVer03WidthEq16, McHorVer13WidthEq16, McHorVer23WidthEq16, McHorVer33WidthEq16 | ||
| 549 | }; | ||
| 550 | #endif | ||
| 551 | |||
| 552 | pFuncList->sMcFuncs.pfLumaHalfpelHor = McHorVer20_c; | ||
| 553 | pFuncList->sMcFuncs.pfLumaHalfpelVer = McHorVer02_c; | ||
| 554 | pFuncList->sMcFuncs.pfLumaHalfpelCen = McHorVer22_c; | ||
| 555 | pFuncList->sMcFuncs.pfSampleAveraging = pfPixAvgFunc; | ||
| 556 | pFuncList->sMcFuncs.pfChromaMc = McChroma_c; | ||
| 557 | fpVerFilter = VerFilter_c; | ||
| 558 | fpHorFilter = HorFilter_c; | ||
| 559 | fpHorFilterInput16Bits = HorFilterInput16bit1_c; | ||
| 560 | McCopyWidthEq4 = McCopyWidthEq4_c; | ||
| 561 | McCopyWidthEq8 = McCopyWidthEq8_c; | ||
| 562 | McCopyWidthEq16 = McCopyWidthEq16_c; | ||
| 563 | pfPixelAvgWidthEq16 = PixelAvgWidthEq16_c; | ||
| 564 | pfMcHorVer02WidthEq16 = McHorVer02WidthEq16_c; | ||
| 565 | pfMcHorVer20WidthEq16 = McHorVer20WidthEq16_c; | ||
| 566 | pfMcHorVer22WidthEq16 = McHorVer22WidthEq16_c; | ||
| 567 | pFuncList->sMcFuncs.pfLumaQuarpelMc = pWelsMcFuncWidthEq16; | ||
| 568 | #if defined (X86_ASM) | ||
| 569 | if ( uiCpuFlag & WELS_CPU_SSE2 ) | ||
| 570 | { | ||
| 571 | pFuncList->sMcFuncs.pfLumaHalfpelHor = McHorVer20_sse2; | ||
| 572 | pFuncList->sMcFuncs.pfLumaHalfpelVer = McHorVer02_sse2; | ||
| 573 | pFuncList->sMcFuncs.pfLumaHalfpelCen = McHorVer22_sse2; | ||
| 574 | pFuncList->sMcFuncs.pfSampleAveraging[0] = PixelAvgWidthEq8_mmx; | ||
| 575 | pFuncList->sMcFuncs.pfSampleAveraging[1] = PixelAvgWidthEq16_sse2; | ||
| 576 | pFuncList->sMcFuncs.pfChromaMc = McChroma_sse2; | ||
| 577 | McCopyWidthEq4 = McCopyWidthEq4_mmx; | ||
| 578 | McCopyWidthEq8 = McCopyWidthEq8_mmx; | ||
| 579 | McCopyWidthEq16 = McCopyWidthEq16_sse2; | ||
| 580 | pfPixelAvgWidthEq16 = PixelAvgWidthEq16_sse2; | ||
| 581 | pfMcHorVer02WidthEq16 = McHorVer02WidthEq16_sse2; | ||
| 582 | pfMcHorVer20WidthEq16 = McHorVer20WidthEq16_sse2; | ||
| 583 | pfMcHorVer22WidthEq16 = McHorVer22WidthEq16_sse2; | ||
| 584 | pFuncList->sMcFuncs.pfLumaQuarpelMc = pWelsMcFuncWidthEq16_sse2; | ||
| 585 | } | ||
| 586 | |||
| 587 | if ( uiCpuFlag & WELS_CPU_SSSE3 ) | ||
| 588 | { | ||
| 589 | pFuncList->sMcFuncs.pfChromaMc = McChroma_ssse3; | ||
| 590 | pFuncList->sMcFuncs.pfSampleAveraging[1] = PixelAvgWidthEq16_ssse3; | ||
| 591 | } | ||
| 592 | |||
| 593 | #endif //(X86_ASM) | ||
| 594 | } | ||
| 595 | } | ||