Showing the changes to codec/encoder/core/src/md.cpp (1 of 308 files). Show all
Unified · Split
| @@ -0,0 +1,1034 @@ | |||
| 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 md.c | ||
| 33 | * | ||
| 34 | * \brief mode decision | ||
| 35 | * | ||
| 36 | * \date 2009.05.14 Created | ||
| 37 | * | ||
| 38 | ************************************************************************************* | ||
| 39 | */ | ||
| 40 | |||
| 41 | #include <string.h> | ||
| 42 | #include "ls_defines.h" | ||
| 43 | #include "encoder_context.h" | ||
| 44 | #include "svc_enc_slice_segment.h" | ||
| 45 | #include "md.h" | ||
| 46 | #include "mc.h" | ||
| 47 | #include "mv_pred.h" | ||
| 48 | #include "cpu_core.h" | ||
| 49 | #include "svc_enc_golomb.h" | ||
| 50 | #include "sample.h" | ||
| 51 | #include "array_stack_align.h" | ||
| 52 | |||
| 53 | namespace WelsSVCEnc { | ||
| 54 | #define INTRA_VARIANCE_SAD_THRESHOLD 150 | ||
| 55 | #define INTER_VARIANCE_SAD_THRESHOLD 20 | ||
| 56 | |||
| 57 | //fill cache of neighbor MB, containing pNonZeroCount, sample_avail, pIntra4x4PredMode | ||
| 58 | void FillNeighborCacheIntra(SMbCache* pMbCache, SMB* pCurMb, int32_t iMbWidth) | ||
| 59 | { | ||
| 60 | uint32_t uiNeighborAvail = pCurMb->uiNeighborAvail; | ||
| 61 | uint32_t uiNeighborIntra = 0; | ||
| 62 | |||
| 63 | if (uiNeighborAvail & LEFT_MB_POS) //LEFT MB | ||
| 64 | { | ||
| 65 | int8_t* pLeftMbNonZeroCount = pCurMb->pNonZeroCount - MB_LUMA_CHROMA_BLOCK4x4_NUM; | ||
| 66 | pMbCache->iNonZeroCoeffCount[8] = pLeftMbNonZeroCount[ 3]; | ||
| 67 | pMbCache->iNonZeroCoeffCount[16] = pLeftMbNonZeroCount[ 7]; | ||
| 68 | pMbCache->iNonZeroCoeffCount[24] = pLeftMbNonZeroCount[11]; | ||
| 69 | pMbCache->iNonZeroCoeffCount[32] = pLeftMbNonZeroCount[15]; | ||
| 70 | |||
| 71 | pMbCache->iNonZeroCoeffCount[ 13] = pLeftMbNonZeroCount[17]; | ||
| 72 | pMbCache->iNonZeroCoeffCount[21] = pLeftMbNonZeroCount[21]; | ||
| 73 | pMbCache->iNonZeroCoeffCount[37] = pLeftMbNonZeroCount[19]; | ||
| 74 | pMbCache->iNonZeroCoeffCount[45] = pLeftMbNonZeroCount[23]; | ||
| 75 | |||
| 76 | uiNeighborIntra |= LEFT_MB_POS; | ||
| 77 | |||
| 78 | if ( IS_INTRA4x4((pCurMb-1)->uiMbType ) ) | ||
| 79 | { | ||
| 80 | int8_t* pLeftMbIntra4x4PredMode = pCurMb->pIntra4x4PredMode - INTRA_4x4_MODE_NUM; | ||
| 81 | pMbCache->iIntraPredMode[8] = pLeftMbIntra4x4PredMode[4]; | ||
| 82 | pMbCache->iIntraPredMode[16] = pLeftMbIntra4x4PredMode[5]; | ||
| 83 | pMbCache->iIntraPredMode[24] = pLeftMbIntra4x4PredMode[6]; | ||
| 84 | pMbCache->iIntraPredMode[32] = pLeftMbIntra4x4PredMode[3]; | ||
| 85 | } | ||
| 86 | else// if ( 0 == constrained_intra_pred_flag || IS_INTRA16x16((pCurMb-1)->uiMbType )) | ||
| 87 | { | ||
| 88 | pMbCache->iIntraPredMode[8] = | ||
| 89 | pMbCache->iIntraPredMode[16] = | ||
| 90 | pMbCache->iIntraPredMode[24] = | ||
| 91 | pMbCache->iIntraPredMode[32] = 2; //DC | ||
| 92 | } | ||
| 93 | } | ||
| 94 | else | ||
| 95 | { | ||
| 96 | pMbCache->iNonZeroCoeffCount[ 8] = | ||
| 97 | pMbCache->iNonZeroCoeffCount[16] = | ||
| 98 | pMbCache->iNonZeroCoeffCount[24] = | ||
| 99 | pMbCache->iNonZeroCoeffCount[32] = -1;//unavailable | ||
| 100 | pMbCache->iNonZeroCoeffCount[13] = | ||
| 101 | pMbCache->iNonZeroCoeffCount[21] = | ||
| 102 | pMbCache->iNonZeroCoeffCount[37] = | ||
| 103 | pMbCache->iNonZeroCoeffCount[45] = -1;//unavailable | ||
| 104 | |||
| 105 | pMbCache->iIntraPredMode[8] = | ||
| 106 | pMbCache->iIntraPredMode[16] = | ||
| 107 | pMbCache->iIntraPredMode[24] = | ||
| 108 | pMbCache->iIntraPredMode[32] = -1;//unavailable | ||
| 109 | } | ||
| 110 | |||
| 111 | if (uiNeighborAvail & TOP_MB_POS)//TOP MB | ||
| 112 | { | ||
| 113 | SMB* pTopMb = pCurMb - iMbWidth; | ||
| 114 | ST32(&pMbCache->iNonZeroCoeffCount[1], LD32(&pTopMb->pNonZeroCount[12])); | ||
| 115 | |||
| 116 | ST16(&pMbCache->iNonZeroCoeffCount[6], LD16(&pTopMb->pNonZeroCount[20])); | ||
| 117 | ST16(&pMbCache->iNonZeroCoeffCount[30], LD16(&pTopMb->pNonZeroCount[22])); | ||
| 118 | |||
| 119 | uiNeighborIntra |= TOP_MB_POS; | ||
| 120 | |||
| 121 | if ( IS_INTRA4x4( pTopMb->uiMbType ) ) | ||
| 122 | { | ||
| 123 | ST32(pMbCache->iIntraPredMode+1, LD32(&pTopMb->pIntra4x4PredMode[0])); | ||
| 124 | } | ||
| 125 | else// if ( 0 == constrained_intra_pred_flag || IS_INTRA16x16( pTopMb->uiMbType )) | ||
| 126 | { | ||
| 127 | const uint32_t kuiDc32 = 0x02020202; | ||
| 128 | ST32( pMbCache->iIntraPredMode+1 , kuiDc32 ); | ||
| 129 | } | ||
| 130 | } | ||
| 131 | else | ||
| 132 | { | ||
| 133 | const uint32_t kuiUnavail32 = 0xffffffff; | ||
| 134 | ST32( pMbCache->iIntraPredMode+1 , kuiUnavail32 ); | ||
| 135 | ST32( &pMbCache->iNonZeroCoeffCount[1], kuiUnavail32 ); | ||
| 136 | |||
| 137 | ST16( &pMbCache->iNonZeroCoeffCount[6], 0xffff ); | ||
| 138 | ST16( &pMbCache->iNonZeroCoeffCount[30], 0xffff ); | ||
| 139 | } | ||
| 140 | |||
| 141 | if (uiNeighborAvail & TOPLEFT_MB_POS) | ||
| 142 | { | ||
| 143 | uiNeighborIntra |= 0x04; | ||
| 144 | } | ||
| 145 | |||
| 146 | |||
| 147 | if (uiNeighborAvail & TOPRIGHT_MB_POS) | ||
| 148 | { | ||
| 149 | uiNeighborIntra |= 0x08; | ||
| 150 | } | ||
| 151 | pMbCache->uiNeighborIntra = uiNeighborIntra; | ||
| 152 | } | ||
| 153 | //fill cache of neighbor MB, containing motion_vector and uiRefIndex | ||
| 154 | void FillNeighborCacheInterWithoutBGD(SMbCache* pMbCache, SMB* pCurMb, int32_t iMbWidth, int8_t *pVaaBgMbFlag) | ||
| 155 | { | ||
| 156 | uint32_t uiNeighborAvail = pCurMb->uiNeighborAvail; | ||
| 157 | SMB* pLeftMb = pCurMb -1 ; | ||
| 158 | SMB* pTopMb = pCurMb -iMbWidth; | ||
| 159 | SMB* pLeftTopMb = pCurMb - iMbWidth - 1 ; | ||
| 160 | SMB* iRightTopMb = pCurMb -iMbWidth + 1 ; | ||
| 161 | SMVComponentUnit *pMvComp = &pMbCache->sMvComponents; | ||
| 162 | if( (uiNeighborAvail & LEFT_MB_POS) && IS_SVC_INTER(pLeftMb->uiMbType) ) | ||
| 163 | { | ||
| 164 | pMvComp->sMotionVectorCache[ 6] = pLeftMb->sMv[ 3]; | ||
| 165 | pMvComp->sMotionVectorCache[12] = pLeftMb->sMv[ 7]; | ||
| 166 | pMvComp->sMotionVectorCache[18] = pLeftMb->sMv[11]; | ||
| 167 | pMvComp->sMotionVectorCache[24] = pLeftMb->sMv[15]; | ||
| 168 | pMvComp->iRefIndexCache[ 6] = pLeftMb->pRefIndex[1]; | ||
| 169 | pMvComp->iRefIndexCache[12] = pLeftMb->pRefIndex[1]; | ||
| 170 | pMvComp->iRefIndexCache[18] = pLeftMb->pRefIndex[3]; | ||
| 171 | pMvComp->iRefIndexCache[24] = pLeftMb->pRefIndex[3]; | ||
| 172 | pMbCache->iSadCost[3] = pLeftMb->pSadCost[0]; | ||
| 173 | |||
| 174 | if ( pLeftMb->uiMbType == MB_TYPE_SKIP ) | ||
| 175 | { | ||
| 176 | pMbCache->bMbTypeSkip[3] = 1; | ||
| 177 | pMbCache->iSadCostSkip[3] = pMbCache->pEncSad[-1]; | ||
| 178 | } | ||
| 179 | else | ||
| 180 | { | ||
| 181 | pMbCache->bMbTypeSkip[3] = 0; | ||
| 182 | pMbCache->iSadCostSkip[3] = 0; | ||
| 183 | } | ||
| 184 | } | ||
| 185 | else //avail or non-inter | ||
| 186 | { | ||
| 187 | ST32(&pMvComp->sMotionVectorCache[ 6], 0); | ||
| 188 | ST32(&pMvComp->sMotionVectorCache[12], 0); | ||
| 189 | ST32(&pMvComp->sMotionVectorCache[18], 0); | ||
| 190 | ST32(&pMvComp->sMotionVectorCache[24], 0); | ||
| 191 | pMvComp->iRefIndexCache[ 6] = | ||
| 192 | pMvComp->iRefIndexCache[12] = | ||
| 193 | pMvComp->iRefIndexCache[18] = | ||
| 194 | pMvComp->iRefIndexCache[24] = (uiNeighborAvail & LEFT_MB_POS) ? REF_NOT_IN_LIST : REF_NOT_AVAIL; | ||
| 195 | pMbCache->iSadCost[3] = 0; | ||
| 196 | pMbCache->bMbTypeSkip[3] = 0; | ||
| 197 | pMbCache->iSadCostSkip[3] = 0; | ||
| 198 | } | ||
| 199 | |||
| 200 | if ( (uiNeighborAvail & TOP_MB_POS) && IS_SVC_INTER(pTopMb->uiMbType) ) //TOP MB | ||
| 201 | { | ||
| 202 | ST64(&pMvComp->sMotionVectorCache[1], LD64(&pTopMb->sMv[12])); | ||
| 203 | ST64(&pMvComp->sMotionVectorCache[3], LD64(&pTopMb->sMv[14])); | ||
| 204 | pMvComp->iRefIndexCache[1] = pTopMb->pRefIndex[2]; | ||
| 205 | pMvComp->iRefIndexCache[2] = pTopMb->pRefIndex[2]; | ||
| 206 | pMvComp->iRefIndexCache[3] = pTopMb->pRefIndex[3]; | ||
| 207 | pMvComp->iRefIndexCache[4] = pTopMb->pRefIndex[3]; | ||
| 208 | pMbCache->iSadCost[1] = pTopMb->pSadCost[0]; | ||
| 209 | |||
| 210 | if ( pTopMb->uiMbType == MB_TYPE_SKIP ) | ||
| 211 | { | ||
| 212 | pMbCache->bMbTypeSkip[1] = 1; | ||
| 213 | pMbCache->iSadCostSkip[1] = pMbCache->pEncSad[-iMbWidth]; | ||
| 214 | } | ||
| 215 | else | ||
| 216 | { | ||
| 217 | pMbCache->bMbTypeSkip[1] = 0; | ||
| 218 | pMbCache->iSadCostSkip[1] = 0; | ||
| 219 | } | ||
| 220 | } | ||
| 221 | else //unavail | ||
| 222 | { | ||
| 223 | ST64(&pMvComp->sMotionVectorCache[1], 0); | ||
| 224 | ST64(&pMvComp->sMotionVectorCache[3], 0); | ||
| 225 | pMvComp->iRefIndexCache[1] = | ||
| 226 | pMvComp->iRefIndexCache[2] = | ||
| 227 | pMvComp->iRefIndexCache[3] = | ||
| 228 | pMvComp->iRefIndexCache[4] = (uiNeighborAvail & TOP_MB_POS) ? REF_NOT_IN_LIST : REF_NOT_AVAIL; | ||
| 229 | pMbCache->iSadCost[1] = 0; | ||
| 230 | |||
| 231 | pMbCache->bMbTypeSkip[1] = 0; | ||
| 232 | pMbCache->iSadCostSkip[1] = 0; | ||
| 233 | } | ||
| 234 | |||
| 235 | if ( (uiNeighborAvail & TOPLEFT_MB_POS) && IS_SVC_INTER(pLeftTopMb->uiMbType) ) //LEFT_TOP MB | ||
| 236 | { | ||
| 237 | pMvComp->sMotionVectorCache[0] = pLeftTopMb->sMv[15]; | ||
| 238 | pMvComp->iRefIndexCache[0] = pLeftTopMb->pRefIndex[3]; | ||
| 239 | pMbCache->iSadCost[0] = pLeftTopMb->pSadCost[0]; | ||
| 240 | |||
| 241 | if ( pLeftTopMb->uiMbType == MB_TYPE_SKIP ) | ||
| 242 | { | ||
| 243 | pMbCache->bMbTypeSkip[0] = 1; | ||
| 244 | pMbCache->iSadCostSkip[0] = pMbCache->pEncSad[-iMbWidth-1]; | ||
| 245 | } | ||
| 246 | else | ||
| 247 | { | ||
| 248 | pMbCache->bMbTypeSkip[0] = 0; | ||
| 249 | pMbCache->iSadCostSkip[0] = 0; | ||
| 250 | } | ||
| 251 | } | ||
| 252 | else //unavail | ||
| 253 | { | ||
| 254 | ST32(&pMvComp->sMotionVectorCache[0], 0); | ||
| 255 | pMvComp->iRefIndexCache[0] = (uiNeighborAvail & TOPLEFT_MB_POS) ? REF_NOT_IN_LIST : REF_NOT_AVAIL; | ||
| 256 | pMbCache->iSadCost[0] = 0; | ||
| 257 | pMbCache->bMbTypeSkip[0] = 0; | ||
| 258 | pMbCache->iSadCostSkip[0] = 0; | ||
| 259 | } | ||
| 260 | |||
| 261 | if ((uiNeighborAvail & TOPRIGHT_MB_POS) && IS_SVC_INTER(iRightTopMb->uiMbType) ) //RIGHT_TOP MB | ||
| 262 | { | ||
| 263 | pMvComp->sMotionVectorCache[5] = iRightTopMb->sMv[12]; | ||
| 264 | pMvComp->iRefIndexCache[5] = iRightTopMb->pRefIndex[2]; | ||
| 265 | pMbCache->iSadCost[2] = iRightTopMb->pSadCost[0]; | ||
| 266 | |||
| 267 | if ( iRightTopMb->uiMbType == MB_TYPE_SKIP ) | ||
| 268 | { | ||
| 269 | pMbCache->bMbTypeSkip[2] = 1; | ||
| 270 | pMbCache->iSadCostSkip[2] = pMbCache->pEncSad[-iMbWidth+1]; | ||
| 271 | } | ||
| 272 | else | ||
| 273 | { | ||
| 274 | pMbCache->bMbTypeSkip[2] = 0; | ||
| 275 | pMbCache->iSadCostSkip[2] = 0; | ||
| 276 | } | ||
| 277 | } | ||
| 278 | else //unavail | ||
| 279 | { | ||
| 280 | ST32(&pMvComp->sMotionVectorCache[5], 0); | ||
| 281 | pMvComp->iRefIndexCache[5] = (uiNeighborAvail & TOPRIGHT_MB_POS) ? REF_NOT_IN_LIST : REF_NOT_AVAIL; | ||
| 282 | pMbCache->iSadCost[2] = 0; | ||
| 283 | pMbCache->bMbTypeSkip[2] = 0; | ||
| 284 | pMbCache->iSadCostSkip[2] = 0; | ||
| 285 | } | ||
| 286 | |||
| 287 | //right-top 4*4 pBlock unavailable | ||
| 288 | ST32(&pMvComp->sMotionVectorCache[ 9], 0); | ||
| 289 | ST32(&pMvComp->sMotionVectorCache[21], 0); | ||
| 290 | ST32(&pMvComp->sMotionVectorCache[11], 0); | ||
| 291 | ST32(&pMvComp->sMotionVectorCache[17], 0); | ||
| 292 | ST32(&pMvComp->sMotionVectorCache[23], 0); | ||
| 293 | pMvComp->iRefIndexCache[ 9] = | ||
| 294 | pMvComp->iRefIndexCache[11] = | ||
| 295 | pMvComp->iRefIndexCache[17] = | ||
| 296 | pMvComp->iRefIndexCache[21] = | ||
| 297 | pMvComp->iRefIndexCache[23] = REF_NOT_AVAIL; | ||
| 298 | } | ||
| 299 | |||
| 300 | void FillNeighborCacheInterWithBGD(SMbCache* pMbCache, SMB* pCurMb, int32_t iMbWidth, int8_t *pVaaBgMbFlag) | ||
| 301 | { | ||
| 302 | uint32_t uiNeighborAvail = pCurMb->uiNeighborAvail; | ||
| 303 | SMB* pLeftMb = pCurMb -1 ; | ||
| 304 | SMB* pTopMb = pCurMb -iMbWidth; | ||
| 305 | SMB* pLeftTopMb = pCurMb - iMbWidth - 1 ; | ||
| 306 | SMB* iRightTopMb = pCurMb -iMbWidth + 1 ; | ||
| 307 | SMVComponentUnit *pMvComp = &pMbCache->sMvComponents; | ||
| 308 | |||
| 309 | if( (uiNeighborAvail & LEFT_MB_POS) && IS_SVC_INTER(pLeftMb->uiMbType) ) | ||
| 310 | { | ||
| 311 | pMvComp->sMotionVectorCache[ 6] = pLeftMb->sMv[ 3]; | ||
| 312 | pMvComp->sMotionVectorCache[12] = pLeftMb->sMv[ 7]; | ||
| 313 | pMvComp->sMotionVectorCache[18] = pLeftMb->sMv[11]; | ||
| 314 | pMvComp->sMotionVectorCache[24] = pLeftMb->sMv[15]; | ||
| 315 | pMvComp->iRefIndexCache[ 6] = pLeftMb->pRefIndex[1]; | ||
| 316 | pMvComp->iRefIndexCache[12] = pLeftMb->pRefIndex[1]; | ||
| 317 | pMvComp->iRefIndexCache[18] = pLeftMb->pRefIndex[3]; | ||
| 318 | pMvComp->iRefIndexCache[24] = pLeftMb->pRefIndex[3]; | ||
| 319 | pMbCache->iSadCost[3] = pLeftMb->pSadCost[0]; | ||
| 320 | |||
| 321 | if ( pLeftMb->uiMbType == MB_TYPE_SKIP && pVaaBgMbFlag[-1] == 0) | ||
| 322 | { | ||
| 323 | pMbCache->bMbTypeSkip[3] = 1; | ||
| 324 | pMbCache->iSadCostSkip[3] = pMbCache->pEncSad[-1]; | ||
| 325 | } | ||
| 326 | else | ||
| 327 | { | ||
| 328 | pMbCache->bMbTypeSkip[3] = 0; | ||
| 329 | pMbCache->iSadCostSkip[3] = 0; | ||
| 330 | } | ||
| 331 | } | ||
| 332 | else //avail or non-inter | ||
| 333 | { | ||
| 334 | ST32(&pMvComp->sMotionVectorCache[ 6], 0); | ||
| 335 | ST32(&pMvComp->sMotionVectorCache[12], 0); | ||
| 336 | ST32(&pMvComp->sMotionVectorCache[18], 0); | ||
| 337 | ST32(&pMvComp->sMotionVectorCache[24], 0); | ||
| 338 | pMvComp->iRefIndexCache[ 6] = | ||
| 339 | pMvComp->iRefIndexCache[12] = | ||
| 340 | pMvComp->iRefIndexCache[18] = | ||
| 341 | pMvComp->iRefIndexCache[24] = (uiNeighborAvail & LEFT_MB_POS) ? REF_NOT_IN_LIST : REF_NOT_AVAIL; | ||
| 342 | pMbCache->iSadCost[3] = 0; | ||
| 343 | pMbCache->bMbTypeSkip[3] = 0; | ||
| 344 | pMbCache->iSadCostSkip[3] = 0; | ||
| 345 | } | ||
| 346 | |||
| 347 | if ( (uiNeighborAvail & TOP_MB_POS) && IS_SVC_INTER(pTopMb->uiMbType) ) //TOP MB | ||
| 348 | { | ||
| 349 | ST64(&pMvComp->sMotionVectorCache[1], LD64(&pTopMb->sMv[12])); | ||
| 350 | ST64(&pMvComp->sMotionVectorCache[3], LD64(&pTopMb->sMv[14])); | ||
| 351 | pMvComp->iRefIndexCache[1] = pTopMb->pRefIndex[2]; | ||
| 352 | pMvComp->iRefIndexCache[2] = pTopMb->pRefIndex[2]; | ||
| 353 | pMvComp->iRefIndexCache[3] = pTopMb->pRefIndex[3]; | ||
| 354 | pMvComp->iRefIndexCache[4] = pTopMb->pRefIndex[3]; | ||
| 355 | pMbCache->iSadCost[1] = pTopMb->pSadCost[0]; | ||
| 356 | if ( pTopMb->uiMbType == MB_TYPE_SKIP && pVaaBgMbFlag[-iMbWidth] == 0 ) | ||
| 357 | { | ||
| 358 | pMbCache->bMbTypeSkip[1] = 1; | ||
| 359 | pMbCache->iSadCostSkip[1] = pMbCache->pEncSad[-iMbWidth]; | ||
| 360 | } | ||
| 361 | else | ||
| 362 | { | ||
| 363 | pMbCache->bMbTypeSkip[1] = 0; | ||
| 364 | pMbCache->iSadCostSkip[1] = 0; | ||
| 365 | } | ||
| 366 | } | ||
| 367 | else //unavail | ||
| 368 | { | ||
| 369 | ST64(&pMvComp->sMotionVectorCache[1], 0); | ||
| 370 | ST64(&pMvComp->sMotionVectorCache[3], 0); | ||
| 371 | pMvComp->iRefIndexCache[1] = | ||
| 372 | pMvComp->iRefIndexCache[2] = | ||
| 373 | pMvComp->iRefIndexCache[3] = | ||
| 374 | pMvComp->iRefIndexCache[4] = (uiNeighborAvail & TOP_MB_POS) ? REF_NOT_IN_LIST : REF_NOT_AVAIL; | ||
| 375 | pMbCache->iSadCost[1] = 0; | ||
| 376 | pMbCache->bMbTypeSkip[1] = 0; | ||
| 377 | pMbCache->iSadCostSkip[1] = 0; | ||
| 378 | } | ||
| 379 | |||
| 380 | |||
| 381 | if ( (uiNeighborAvail & TOPLEFT_MB_POS) && IS_SVC_INTER(pLeftTopMb->uiMbType) ) //LEFT_TOP MB | ||
| 382 | { | ||
| 383 | pMvComp->sMotionVectorCache[0] = pLeftTopMb->sMv[15]; | ||
| 384 | pMvComp->iRefIndexCache[0] = pLeftTopMb->pRefIndex[3]; | ||
| 385 | pMbCache->iSadCost[0] = pLeftTopMb->pSadCost[0]; | ||
| 386 | |||
| 387 | if ( pLeftTopMb->uiMbType == MB_TYPE_SKIP && pVaaBgMbFlag[-iMbWidth-1] == 0 ) | ||
| 388 | { | ||
| 389 | pMbCache->bMbTypeSkip[0] = 1; | ||
| 390 | pMbCache->iSadCostSkip[0] = pMbCache->pEncSad[-iMbWidth-1]; | ||
| 391 | } | ||
| 392 | else | ||
| 393 | { | ||
| 394 | pMbCache->bMbTypeSkip[0] = 0; | ||
| 395 | pMbCache->iSadCostSkip[0] = 0; | ||
| 396 | } | ||
| 397 | } | ||
| 398 | else //unavail | ||
| 399 | { | ||
| 400 | ST32(&pMvComp->sMotionVectorCache[0], 0); | ||
| 401 | pMvComp->iRefIndexCache[0] = (uiNeighborAvail & TOPLEFT_MB_POS) ? REF_NOT_IN_LIST : REF_NOT_AVAIL; | ||
| 402 | pMbCache->iSadCost[0] = 0; | ||
| 403 | pMbCache->bMbTypeSkip[0] = 0; | ||
| 404 | pMbCache->iSadCostSkip[0] = 0; | ||
| 405 | } | ||
| 406 | |||
| 407 | if ((uiNeighborAvail & TOPRIGHT_MB_POS) && IS_SVC_INTER(iRightTopMb->uiMbType) ) //RIGHT_TOP MB | ||
| 408 | { | ||
| 409 | pMvComp->sMotionVectorCache[5] = iRightTopMb->sMv[12]; | ||
| 410 | pMvComp->iRefIndexCache[5] = iRightTopMb->pRefIndex[2]; | ||
| 411 | pMbCache->iSadCost[2] = iRightTopMb->pSadCost[0]; | ||
| 412 | |||
| 413 | if ( iRightTopMb->uiMbType == MB_TYPE_SKIP && pVaaBgMbFlag[-iMbWidth+1] == 0 ) | ||
| 414 | { | ||
| 415 | pMbCache->bMbTypeSkip[2] = 1; | ||
| 416 | pMbCache->iSadCostSkip[2] = pMbCache->pEncSad[-iMbWidth+1]; | ||
| 417 | } | ||
| 418 | else | ||
| 419 | { | ||
| 420 | pMbCache->bMbTypeSkip[2] = 0; | ||
| 421 | pMbCache->iSadCostSkip[2] = 0; | ||
| 422 | } | ||
| 423 | } | ||
| 424 | else //unavail | ||
| 425 | { | ||
| 426 | ST32(&pMvComp->sMotionVectorCache[5], 0); | ||
| 427 | pMvComp->iRefIndexCache[5] = (uiNeighborAvail & TOPRIGHT_MB_POS) ? REF_NOT_IN_LIST : REF_NOT_AVAIL; | ||
| 428 | pMbCache->iSadCost[2] = 0; | ||
| 429 | pMbCache->bMbTypeSkip[2] = 0; | ||
| 430 | pMbCache->iSadCostSkip[2] = 0; | ||
| 431 | } | ||
| 432 | |||
| 433 | //right-top 4*4 pBlock unavailable | ||
| 434 | ST32(&pMvComp->sMotionVectorCache[ 9], 0); | ||
| 435 | ST32(&pMvComp->sMotionVectorCache[21], 0); | ||
| 436 | ST32(&pMvComp->sMotionVectorCache[11], 0); | ||
| 437 | ST32(&pMvComp->sMotionVectorCache[17], 0); | ||
| 438 | ST32(&pMvComp->sMotionVectorCache[23], 0); | ||
| 439 | pMvComp->iRefIndexCache[ 9] = | ||
| 440 | pMvComp->iRefIndexCache[11] = | ||
| 441 | pMvComp->iRefIndexCache[17] = | ||
| 442 | pMvComp->iRefIndexCache[21] = | ||
| 443 | pMvComp->iRefIndexCache[23] = REF_NOT_AVAIL; | ||
| 444 | } | ||
| 445 | |||
| 446 | void InitFillNeighborCacheInterFunc( SWelsFuncPtrList *pFuncList, const int32_t kiFlag ) | ||
| 447 | { | ||
| 448 | pFuncList->pfFillInterNeighborCache = kiFlag ? FillNeighborCacheInterWithBGD : FillNeighborCacheInterWithoutBGD; | ||
| 449 | } | ||
| 450 | |||
| 451 | void UpdateMbMv_c( SMVUnitXY *pMvBuffer, const SMVUnitXY ksMv ) | ||
| 452 | { | ||
| 453 | int32_t k = 0; | ||
| 454 | for (; k < MB_BLOCK4x4_NUM; k += 4) | ||
| 455 | { | ||
| 456 | pMvBuffer[k ] = | ||
| 457 | pMvBuffer[k+1] = | ||
| 458 | pMvBuffer[k+2] = | ||
| 459 | pMvBuffer[k+3] = ksMv; | ||
| 460 | } | ||
| 461 | } | ||
| 462 | |||
| 463 | |||
| 464 | uint8_t MdInterAnalysisVaaInfo_c( int32_t *pSad8x8 ) | ||
| 465 | { | ||
| 466 | int32_t iSadBlock[4], iAverageSadBlock[4]; | ||
| 467 | int32_t iAverageSad, iVarianceSad; | ||
| 468 | |||
| 469 | iSadBlock[0] = pSad8x8[0]; | ||
| 470 | iAverageSad = iSadBlock[0]; | ||
| 471 | |||
| 472 | iSadBlock[1] = pSad8x8[1]; | ||
| 473 | iAverageSad += iSadBlock[1]; | ||
| 474 | |||
| 475 | iSadBlock[2] = pSad8x8[2]; | ||
| 476 | iAverageSad += iSadBlock[2]; | ||
| 477 | |||
| 478 | iSadBlock[3] = pSad8x8[3]; | ||
| 479 | iAverageSad += iSadBlock[3]; | ||
| 480 | |||
| 481 | iAverageSad = iAverageSad >> 2; | ||
| 482 | |||
| 483 | iAverageSadBlock[0] = (iSadBlock[0] >> 6) - (iAverageSad >> 6); | ||
| 484 | iVarianceSad = iAverageSadBlock[0] * iAverageSadBlock[0]; | ||
| 485 | |||
| 486 | iAverageSadBlock[1] = (iSadBlock[1] >> 6) - (iAverageSad >> 6); | ||
| 487 | iVarianceSad += iAverageSadBlock[1] * iAverageSadBlock[1]; | ||
| 488 | |||
| 489 | iAverageSadBlock[2] = (iSadBlock[2] >> 6) - (iAverageSad >> 6); | ||
| 490 | iVarianceSad += iAverageSadBlock[2] * iAverageSadBlock[2]; | ||
| 491 | |||
| 492 | iAverageSadBlock[3] = (iSadBlock[3] >> 6) - (iAverageSad >> 6); | ||
| 493 | iVarianceSad += iAverageSadBlock[3] * iAverageSadBlock[3]; | ||
| 494 | |||
| 495 | if ( iVarianceSad < INTER_VARIANCE_SAD_THRESHOLD ) | ||
| 496 | { | ||
| 497 | return 15; | ||
| 498 | } | ||
| 499 | |||
| 500 | uint8_t uiMbSign = 0; | ||
| 501 | if (iSadBlock[0] > iAverageSad) | ||
| 502 | uiMbSign |= 0x08; | ||
| 503 | if (iSadBlock[1] > iAverageSad) | ||
| 504 | uiMbSign |= 0x04; | ||
| 505 | if (iSadBlock[2] > iAverageSad) | ||
| 506 | uiMbSign |= 0x02; | ||
| 507 | if (iSadBlock[3] > iAverageSad) | ||
| 508 | uiMbSign |= 0x01; | ||
| 509 | return ( uiMbSign ); | ||
| 510 | } | ||
| 511 | |||
| 512 | static inline int32_t AnalysisVaaInfoIntra_c( uint8_t *pDataY, const int32_t kiLineSize ) | ||
| 513 | { | ||
| 514 | ENFORCE_STACK_ALIGN_1D(uint16_t, uiAvgBlock, 16, 16) | ||
| 515 | uint16_t *pBlock = &uiAvgBlock[0]; | ||
| 516 | uint8_t *pEncData = pDataY; | ||
| 517 | const int32_t kiLineSize2 = kiLineSize << 1; | ||
| 518 | const int32_t kiLineSize3 = kiLineSize + kiLineSize2; | ||
| 519 | const int32_t kiLineSize4 = kiLineSize << 2; | ||
| 520 | int32_t i = 0, j = 0, num = 0; | ||
| 521 | int32_t iSumAvg = 0, iSumSqr = 0; | ||
| 522 | |||
| 523 | // analysis_vaa_info_intra_core_c( pDataY, iLineSize, pBlock ); | ||
| 524 | for ( ; j < 16; j += 4 ) | ||
| 525 | { | ||
| 526 | num = 0; | ||
| 527 | for ( i = 0; i < 16; i += 4, num ++ ) | ||
| 528 | { | ||
| 529 | pBlock[num] = pEncData[i ] + pEncData[i+1 ] + pEncData[i+2 ] + pEncData[i+3 ]; | ||
| 530 | pBlock[num] += pEncData[i+kiLineSize ] + pEncData[i+kiLineSize+1 ] + pEncData[i+kiLineSize+2 ] + pEncData[i+kiLineSize+3 ]; | ||
| 531 | pBlock[num] += pEncData[i+kiLineSize2] + pEncData[i+kiLineSize2+1] + pEncData[i+kiLineSize2+2] + pEncData[i+kiLineSize2+3]; | ||
| 532 | pBlock[num] += pEncData[i+kiLineSize3] + pEncData[i+kiLineSize3+1] + pEncData[i+kiLineSize3+2] + pEncData[i+kiLineSize3+3]; | ||
| 533 | pBlock[num] >>= 4; | ||
| 534 | } | ||
| 535 | pBlock += 4; | ||
| 536 | pEncData += kiLineSize4; | ||
| 537 | } | ||
| 538 | |||
| 539 | pBlock = &uiAvgBlock[0]; | ||
| 540 | i = 4; | ||
| 541 | for ( ; i > 0; --i ) | ||
| 542 | { | ||
| 543 | iSumAvg += pBlock[0] + pBlock[1] + pBlock[2] + pBlock[3]; | ||
| 544 | iSumSqr += pBlock[0] * pBlock[0] + pBlock[1] * pBlock[1] + pBlock[2] * pBlock[2] + pBlock[3] * pBlock[3]; | ||
| 545 | |||
| 546 | pBlock += 4; | ||
| 547 | } | ||
| 548 | |||
| 549 | |||
| 550 | return /*variance =*/ (iSumSqr - ((iSumAvg * iSumAvg) >> 4)); | ||
| 551 | } | ||
| 552 | |||
| 553 | // for pfGetVarianceFromIntraVaa function ptr adaptive by CPU features, 6/7/2010 | ||
| 554 | void InitIntraAnalysisVaaInfo( SWelsFuncPtrList *pFuncList, const uint32_t kuiCpuFlag ) | ||
| 555 | { | ||
| 556 | pFuncList->pfGetVarianceFromIntraVaa = AnalysisVaaInfoIntra_c; | ||
| 557 | pFuncList->pfGetMbSignFromInterVaa = MdInterAnalysisVaaInfo_c; | ||
| 558 | pFuncList->pfUpdateMbMv = UpdateMbMv_c; | ||
| 559 | |||
| 560 | #if defined(X86_ASM) | ||
| 561 | if ( (kuiCpuFlag & WELS_CPU_SSE2) == WELS_CPU_SSE2 ) | ||
| 562 | { | ||
| 563 | pFuncList->pfGetVarianceFromIntraVaa = AnalysisVaaInfoIntra_sse2; | ||
| 564 | pFuncList->pfGetMbSignFromInterVaa = MdInterAnalysisVaaInfo_sse2; | ||
| 565 | pFuncList->pfUpdateMbMv = UpdateMbMv_sse2; | ||
| 566 | } | ||
| 567 | if ( (kuiCpuFlag & WELS_CPU_SSSE3) == WELS_CPU_SSSE3 ) | ||
| 568 | { | ||
| 569 | pFuncList->pfGetVarianceFromIntraVaa = AnalysisVaaInfoIntra_ssse3; | ||
| 570 | } | ||
| 571 | if ( (kuiCpuFlag & WELS_CPU_SSE41) == WELS_CPU_SSE41 ) | ||
| 572 | { | ||
| 573 | pFuncList->pfGetMbSignFromInterVaa = MdInterAnalysisVaaInfo_sse41; | ||
| 574 | } | ||
| 575 | #endif//X86_ASM | ||
| 576 | } | ||
| 577 | |||
| 578 | BOOL_T MdIntraAnalysisVaaInfo( sWelsEncCtx* pEncCtx, uint8_t* pEncMb ) | ||
| 579 | { | ||
| 580 | |||
| 581 | SDqLayer* pCurDqLayer = pEncCtx->pCurDqLayer; | ||
| 582 | const int32_t kiLineSize = pCurDqLayer->iEncStride[0]; | ||
| 583 | const int32_t kiVariance = pEncCtx->pFuncList->pfGetVarianceFromIntraVaa( pEncMb, kiLineSize ); | ||
| 584 | return (kiVariance >= INTRA_VARIANCE_SAD_THRESHOLD); | ||
| 585 | } | ||
| 586 | |||
| 587 | void InitMeRefinePointer(SMeRefinePointer* pMeRefine, SMbCache* pMbCache, int32_t iStride) | ||
| 588 | { | ||
| 589 | pMeRefine->pHalfPixH = &pMbCache->pBufferInterPredMe[0] + iStride; | ||
| 590 | pMeRefine->pHalfPixV = &pMbCache->pBufferInterPredMe[640] + iStride; | ||
| 591 | |||
| 592 | pMeRefine->pQuarPixBest= &pMbCache->pBufferInterPredMe[1280] + iStride; | ||
| 593 | pMeRefine->pQuarPixTmp = &pMbCache->pBufferInterPredMe[1920] + iStride; | ||
| 594 | } | ||
| 595 | typedef struct TagQuarParams | ||
| 596 | { | ||
| 597 | int32_t iBestCost; | ||
| 598 | int32_t iBestHalfPix; | ||
| 599 | int32_t iStrideA; | ||
| 600 | int32_t iStrideB; | ||
| 601 | uint8_t * pRef; | ||
| 602 | uint8_t * pSrcB[4]; | ||
| 603 | uint8_t * pSrcA[4]; | ||
| 604 | int32_t iLms[4]; | ||
| 605 | int32_t iBestQuarPix; | ||
| 606 | }SQuarRefineParams; | ||
| 607 | |||
| 608 | #define SWITCH_BEST_TMP_BUF(prev_best, curr_best){\ | ||
| 609 | pParams->iBestCost = iCurCost;\ | ||
| 610 | pTmp = prev_best;\ | ||
| 611 | prev_best = curr_best;\ | ||
| 612 | curr_best = pTmp;\ | ||
| 613 | } | ||
| 614 | #define CALC_COST(me_buf, lm) ( pFunc->sSampleDealingFuncs.pfMeCost[kuiPixel](pEncMb, iStrideEnc, me_buf, ME_REFINE_BUF_STRIDE) + lm ) | ||
| 615 | |||
| 616 | inline void MeRefineQuarPixel( SWelsFuncPtrList *pFunc, SWelsME* pMe, SMeRefinePointer* pMeRefine, const int32_t kiWidth, const int32_t kiHeight,SQuarRefineParams *pParams, int32_t iStrideEnc ) | ||
| 617 | { | ||
| 618 | PWelsSampleAveragingFunc *pSampleAvg = pFunc->sMcFuncs.pfSampleAveraging; | ||
| 619 | const int32_t kiAvgIndex = kiWidth >> 4; | ||
| 620 | int32_t iCurCost; | ||
| 621 | uint8_t *pEncMb = pMe->pEncMb; | ||
| 622 | uint8_t *pTmp = NULL; | ||
| 623 | const uint8_t kuiPixel = pMe->uiPixel; | ||
| 624 | |||
| 625 | pSampleAvg[kiAvgIndex](pMeRefine->pQuarPixTmp, ME_REFINE_BUF_STRIDE, pParams->pSrcA[0], ME_REFINE_BUF_STRIDE,pParams->pSrcB[0], pParams->iStrideA, kiHeight); | ||
| 626 | |||
| 627 | iCurCost = CALC_COST(pMeRefine->pQuarPixTmp,pParams->iLms[0]); | ||
| 628 | if (iCurCost < pParams->iBestCost) | ||
| 629 | { | ||
| 630 | pParams->iBestQuarPix = ME_QUAR_PIXEL_TOP; | ||
| 631 | SWITCH_BEST_TMP_BUF(pMeRefine->pQuarPixBest,pMeRefine->pQuarPixTmp); | ||
| 632 | } | ||
| 633 | //=========================(0, 1)=======================// | ||
| 634 | pSampleAvg[kiAvgIndex](pMeRefine->pQuarPixTmp, ME_REFINE_BUF_STRIDE, pParams->pSrcA[1], | ||
| 635 | ME_REFINE_BUF_STRIDE,pParams->pSrcB[1], pParams->iStrideA, kiHeight); | ||
| 636 | iCurCost = CALC_COST(pMeRefine->pQuarPixTmp,pParams->iLms[1]); | ||
| 637 | if (iCurCost < pParams->iBestCost) | ||
| 638 | { | ||
| 639 | pParams->iBestQuarPix = ME_QUAR_PIXEL_BOTTOM; | ||
| 640 | SWITCH_BEST_TMP_BUF(pMeRefine->pQuarPixBest,pMeRefine->pQuarPixTmp); | ||
| 641 | } | ||
| 642 | //==========================(-1, 0)=========================// | ||
| 643 | pSampleAvg[kiAvgIndex](pMeRefine->pQuarPixTmp, ME_REFINE_BUF_STRIDE,pParams->pSrcA[2], | ||
| 644 | ME_REFINE_BUF_STRIDE,pParams->pSrcB[2], pParams->iStrideB, kiHeight); | ||
| 645 | iCurCost = CALC_COST(pMeRefine->pQuarPixTmp,pParams->iLms[2]); | ||
| 646 | if (iCurCost < pParams->iBestCost) | ||
| 647 | { | ||
| 648 | pParams->iBestQuarPix = ME_QUAR_PIXEL_LEFT; | ||
| 649 | SWITCH_BEST_TMP_BUF(pMeRefine->pQuarPixBest,pMeRefine->pQuarPixTmp); | ||
| 650 | } | ||
| 651 | //==========================(1, 0)=========================// | ||
| 652 | pSampleAvg[kiAvgIndex](pMeRefine->pQuarPixTmp, ME_REFINE_BUF_STRIDE,pParams->pSrcA[3], | ||
| 653 | ME_REFINE_BUF_STRIDE, pParams->pSrcB[3], pParams->iStrideB, kiHeight); | ||
| 654 | |||
| 655 | iCurCost = CALC_COST(pMeRefine->pQuarPixTmp,pParams->iLms[3]); | ||
| 656 | if (iCurCost < pParams->iBestCost) | ||
| 657 | { | ||
| 658 | pParams->iBestQuarPix = ME_QUAR_PIXEL_RIGHT; | ||
| 659 | SWITCH_BEST_TMP_BUF(pMeRefine->pQuarPixBest,pMeRefine->pQuarPixTmp); | ||
| 660 | } | ||
| 661 | } | ||
| 662 | |||
| 663 | void MeRefineFracPixel(sWelsEncCtx* pEncCtx, uint8_t* pMemPredInterMb, SWelsME* pMe, | ||
| 664 | SMeRefinePointer* pMeRefine, int32_t iWidth, int32_t iHeight) | ||
| 665 | { | ||
| 666 | SWelsFuncPtrList *pFunc= pEncCtx->pFuncList; | ||
| 667 | int16_t iMvx = pMe->sMv.iMvX; | ||
| 668 | int16_t iMvy = pMe->sMv.iMvY; | ||
| 669 | |||
| 670 | int16_t iHalfMvx = iMvx; | ||
| 671 | int16_t iHalfMvy = iMvy; | ||
| 672 | const int32_t kiStrideEnc = pEncCtx->pCurDqLayer->iEncStride[0]; | ||
| 673 | const int32_t kiStrideRef = pEncCtx->pCurDqLayer->pRefPic->iLineSize[0]; | ||
| 674 | |||
| 675 | uint8_t* pEncData = pMe->pEncMb; | ||
| 676 | uint8_t* pRef = pMe->pRefMb;//091010 | ||
| 677 | |||
| 678 | int32_t iBestQuarPix = ME_NO_BEST_QUAR_PIXEL; | ||
| 679 | |||
| 680 | SQuarRefineParams sParams; | ||
| 681 | static int32_t iMvQuarAddX[10] = {0,0,-1,1,0,0,0,-1,1,0}; | ||
| 682 | int32_t *pMvQuarAddY = iMvQuarAddX + 3; | ||
| 683 | uint8_t* pBestPredInter = pRef; | ||
| 684 | int32_t iInterBlk4Stride = ME_REFINE_BUF_STRIDE; | ||
| 685 | |||
| 686 | int32_t iBestCost; | ||
| 687 | int32_t iCurCost; | ||
| 688 | int32_t iBestHalfPix; | ||
| 689 | |||
| 690 | if ((pFunc->sSampleDealingFuncs.pfMeCost == pFunc->sSampleDealingFuncs.pfSampleSatd) && (pFunc->sSampleDealingFuncs.pfMdCost == pFunc->sSampleDealingFuncs.pfSampleSatd)) | ||
| 691 | { | ||
| 692 | iBestCost = pMe->uSadPredISatd.uiSatd + COST_MVD(pMe->pMvdCost, iMvx - pMe->sMvp.iMvX, iMvy - pMe->sMvp.iMvY); | ||
| 693 | } | ||
| 694 | else | ||
| 695 | { | ||
| 696 | iBestCost = pFunc->sSampleDealingFuncs.pfMeCost[pMe->uiPixel]( pEncData, kiStrideEnc, pRef, kiStrideRef ) + | ||
| 697 | COST_MVD(pMe->pMvdCost, iMvx - pMe->sMvp.iMvX, iMvy - pMe->sMvp.iMvY); | ||
| 698 | } | ||
| 699 | |||
| 700 | iBestHalfPix = REFINE_ME_NO_BEST_HALF_PIXEL; | ||
| 701 | |||
| 702 | pFunc->sMcFuncs.pfLumaHalfpelVer( pRef-kiStrideRef, kiStrideRef, pMeRefine->pHalfPixV, ME_REFINE_BUF_STRIDE, iWidth, iHeight+1 ); | ||
| 703 | |||
| 704 | //step 1: get [iWidth][iHeight+1] half pixel from vertical filter | ||
| 705 | //===========================(0, -2)==============================// | ||
| 706 | iCurCost = pFunc->sSampleDealingFuncs.pfMeCost[pMe->uiPixel](pEncData, kiStrideEnc, pMeRefine->pHalfPixV, ME_REFINE_BUF_STRIDE) + | ||
| 707 | COST_MVD( pMe->pMvdCost, iMvx - pMe->sMvp.iMvX, iMvy - 2 - pMe->sMvp.iMvY ); | ||
| 708 | if(iCurCost < iBestCost) | ||
| 709 | { | ||
| 710 | iBestCost = iCurCost; | ||
| 711 | iBestHalfPix = REFINE_ME_HALF_PIXEL_TOP; | ||
| 712 | pBestPredInter = pMeRefine->pHalfPixV; | ||
| 713 | } | ||
| 714 | //===========================(0, 2)==============================// | ||
| 715 | iCurCost = pFunc->sSampleDealingFuncs.pfMeCost[pMe->uiPixel](pEncData, kiStrideEnc, pMeRefine->pHalfPixV+ME_REFINE_BUF_STRIDE, ME_REFINE_BUF_STRIDE) + | ||
| 716 | COST_MVD( pMe->pMvdCost, iMvx - pMe->sMvp.iMvX, iMvy + 2 - pMe->sMvp.iMvY ); | ||
| 717 | if(iCurCost < iBestCost) | ||
| 718 | { | ||
| 719 | iBestCost = iCurCost; | ||
| 720 | iBestHalfPix = REFINE_ME_HALF_PIXEL_BOTTOM; | ||
| 721 | pBestPredInter = pMeRefine->pHalfPixV+ME_REFINE_BUF_STRIDE; | ||
| 722 | } | ||
| 723 | pFunc->sMcFuncs.pfLumaHalfpelHor( pRef-1, kiStrideRef, pMeRefine->pHalfPixH, ME_REFINE_BUF_STRIDE, iWidth+1, iHeight ); | ||
| 724 | //step 2: get [iWidth][iHeight+1] half pixel from horizon filter | ||
| 725 | |||
| 726 | //===========================(-2, 0)==============================// | ||
| 727 | iCurCost = pFunc->sSampleDealingFuncs.pfMeCost[pMe->uiPixel](pEncData, kiStrideEnc, pMeRefine->pHalfPixH, ME_REFINE_BUF_STRIDE) + | ||
| 728 | COST_MVD( pMe->pMvdCost, iMvx - 2 - pMe->sMvp.iMvX, iMvy - pMe->sMvp.iMvY ); | ||
| 729 | if(iCurCost < iBestCost) | ||
| 730 | { | ||
| 731 | iBestCost = iCurCost; | ||
| 732 | iBestHalfPix = REFINE_ME_HALF_PIXEL_LEFT; | ||
| 733 | pBestPredInter = pMeRefine->pHalfPixH; | ||
| 734 | } | ||
| 735 | //===========================(2, 0)===============================// | ||
| 736 | iCurCost = pFunc->sSampleDealingFuncs.pfMeCost[pMe->uiPixel](pEncData, kiStrideEnc, pMeRefine->pHalfPixH+1, ME_REFINE_BUF_STRIDE) + | ||
| 737 | COST_MVD( pMe->pMvdCost, iMvx + 2 - pMe->sMvp.iMvX, iMvy - pMe->sMvp.iMvY ); | ||
| 738 | if(iCurCost < iBestCost) | ||
| 739 | { | ||
| 740 | iBestCost = iCurCost; | ||
| 741 | iBestHalfPix = REFINE_ME_HALF_PIXEL_RIGHT; | ||
| 742 | pBestPredInter = pMeRefine->pHalfPixH+1; | ||
| 743 | } | ||
| 744 | |||
| 745 | sParams.iBestCost = iBestCost; | ||
| 746 | sParams.iBestHalfPix = iBestHalfPix; | ||
| 747 | sParams.pRef = pRef; | ||
| 748 | sParams.iBestQuarPix = ME_NO_BEST_QUAR_PIXEL; | ||
| 749 | |||
| 750 | //step 5: if no best half-pixel prediction, try quarter pixel prediction | ||
| 751 | // if yes, must get [X+1][X+1] half-pixel from (2, 2) horizontal and vertical filter | ||
| 752 | if (REFINE_ME_NO_BEST_HALF_PIXEL == iBestHalfPix) | ||
| 753 | { | ||
| 754 | sParams.iStrideA = kiStrideRef; | ||
| 755 | sParams.iStrideB = kiStrideRef; | ||
| 756 | sParams.pSrcA[0] = pMeRefine->pHalfPixV; | ||
| 757 | sParams.pSrcA[1] = pMeRefine->pHalfPixV+ME_REFINE_BUF_STRIDE; | ||
| 758 | sParams.pSrcA[2] = pMeRefine->pHalfPixH; | ||
| 759 | sParams.pSrcA[3] = pMeRefine->pHalfPixH+1; | ||
| 760 | |||
| 761 | sParams.pSrcB[0] = sParams.pSrcB[1] = sParams.pSrcB[2] = sParams.pSrcB[3] = pRef; | ||
| 762 | |||
| 763 | sParams.iLms[0] = COST_MVD( pMe->pMvdCost, iHalfMvx - pMe->sMvp.iMvX, iHalfMvy - 1 - pMe->sMvp.iMvY ); | ||
| 764 | sParams.iLms[1] = COST_MVD( pMe->pMvdCost, iHalfMvx - pMe->sMvp.iMvX, iHalfMvy + 1 - pMe->sMvp.iMvY ); | ||
| 765 | sParams.iLms[2] = COST_MVD( pMe->pMvdCost, iHalfMvx - 1 - pMe->sMvp.iMvX, iHalfMvy - pMe->sMvp.iMvY ); | ||
| 766 | sParams.iLms[3] = COST_MVD( pMe->pMvdCost, iHalfMvx + 1 - pMe->sMvp.iMvX, iHalfMvy - pMe->sMvp.iMvY ); | ||
| 767 | } | ||
| 768 | else //must get [X+1][X+1] half-pixel from (2, 2) horizontal and vertical filter | ||
| 769 | { | ||
| 770 | switch(iBestHalfPix) | ||
| 771 | { | ||
| 772 | case REFINE_ME_HALF_PIXEL_LEFT: | ||
| 773 | { | ||
| 774 | pMeRefine->pHalfPixHV = pMeRefine->pHalfPixV;//reuse pBuffer, here only h&hv | ||
| 775 | pFunc->sMcFuncs.pfLumaHalfpelCen( pRef-1-kiStrideRef, kiStrideRef, pMeRefine->pHalfPixHV,ME_REFINE_BUF_STRIDE,iWidth+1, iHeight+1 ); | ||
| 776 | |||
| 777 | iHalfMvx -= 2; | ||
| 778 | sParams.iStrideA = ME_REFINE_BUF_STRIDE; | ||
| 779 | sParams.iStrideB = kiStrideRef; | ||
| 780 | sParams.pSrcA[0] = pMeRefine->pHalfPixH; | ||
| 781 | sParams.pSrcA[3] = sParams.pSrcA[2] = sParams.pSrcA[1] = sParams.pSrcA[0]; | ||
| 782 | sParams.pSrcB[0] = pMeRefine->pHalfPixHV; | ||
| 783 | sParams.pSrcB[1] = pMeRefine->pHalfPixHV+ME_REFINE_BUF_STRIDE; | ||
| 784 | sParams.pSrcB[2] = pRef - 1; | ||
| 785 | sParams.pSrcB[3] = pRef; | ||
| 786 | |||
| 787 | }break; | ||
| 788 | case REFINE_ME_HALF_PIXEL_RIGHT: | ||
| 789 | { | ||
| 790 | pMeRefine->pHalfPixHV = pMeRefine->pHalfPixV;//reuse pBuffer, here only h&hv | ||
| 791 | pFunc->sMcFuncs.pfLumaHalfpelCen( pRef-1-kiStrideRef, kiStrideRef, pMeRefine->pHalfPixHV,ME_REFINE_BUF_STRIDE,iWidth+1, iHeight+1 ); | ||
| 792 | iHalfMvx += 2; | ||
| 793 | sParams.iStrideA = ME_REFINE_BUF_STRIDE; | ||
| 794 | sParams.iStrideB = kiStrideRef; | ||
| 795 | sParams.pSrcA[0] = pMeRefine->pHalfPixH+1; | ||
| 796 | sParams.pSrcA[3] = sParams.pSrcA[2] = sParams.pSrcA[1] = sParams.pSrcA[0]; | ||
| 797 | sParams.pSrcB[0] = pMeRefine->pHalfPixHV+1; | ||
| 798 | sParams.pSrcB[1] = pMeRefine->pHalfPixHV+1+ ME_REFINE_BUF_STRIDE; | ||
| 799 | sParams.pSrcB[2] = pRef; | ||
| 800 | sParams.pSrcB[3] = pRef + 1; | ||
| 801 | }break; | ||
| 802 | case REFINE_ME_HALF_PIXEL_TOP: | ||
| 803 | { | ||
| 804 | pMeRefine->pHalfPixHV = pMeRefine->pHalfPixH;//reuse pBuffer, here only v&hv | ||
| 805 | pFunc->sMcFuncs.pfLumaHalfpelCen( pRef-1-kiStrideRef, kiStrideRef, pMeRefine->pHalfPixHV,ME_REFINE_BUF_STRIDE,iWidth+1, iHeight+1 ); | ||
| 806 | |||
| 807 | iHalfMvy -= 2; | ||
| 808 | sParams.iStrideA = kiStrideRef; | ||
| 809 | sParams.iStrideB = ME_REFINE_BUF_STRIDE; | ||
| 810 | sParams.pSrcA[0] = pMeRefine->pHalfPixV; | ||
| 811 | sParams.pSrcA[3] = sParams.pSrcA[2] = sParams.pSrcA[1] = sParams.pSrcA[0]; | ||
| 812 | sParams.pSrcB[0] = pRef - kiStrideRef; | ||
| 813 | sParams.pSrcB[1] = pRef; | ||
| 814 | sParams.pSrcB[2] = pMeRefine->pHalfPixHV; | ||
| 815 | sParams.pSrcB[3] = pMeRefine->pHalfPixHV+1; | ||
| 816 | }break; | ||
| 817 | case REFINE_ME_HALF_PIXEL_BOTTOM: | ||
| 818 | { | ||
| 819 | pMeRefine->pHalfPixHV = pMeRefine->pHalfPixH;//reuse pBuffer, here only v&hv | ||
| 820 | pFunc->sMcFuncs.pfLumaHalfpelCen( pRef-1-kiStrideRef, kiStrideRef, pMeRefine->pHalfPixHV,ME_REFINE_BUF_STRIDE,iWidth+1, iHeight+1 ); | ||
| 821 | iHalfMvy += 2; | ||
| 822 | sParams.iStrideA = kiStrideRef; | ||
| 823 | sParams.iStrideB = ME_REFINE_BUF_STRIDE; | ||
| 824 | sParams.pSrcA[0] = pMeRefine->pHalfPixV + ME_REFINE_BUF_STRIDE; | ||
| 825 | sParams.pSrcA[3] = sParams.pSrcA[2] = sParams.pSrcA[1] = sParams.pSrcA[0]; | ||
| 826 | sParams.pSrcB[0] = pRef; | ||
| 827 | sParams.pSrcB[1] = pRef + kiStrideRef; | ||
| 828 | sParams.pSrcB[2] = pMeRefine->pHalfPixHV + ME_REFINE_BUF_STRIDE; | ||
| 829 | sParams.pSrcB[3] = pMeRefine->pHalfPixHV + ME_REFINE_BUF_STRIDE + 1; | ||
| 830 | }break; | ||
| 831 | default: | ||
| 832 | break; | ||
| 833 | } | ||
| 834 | sParams.iLms[0] = COST_MVD( pMe->pMvdCost, iHalfMvx - pMe->sMvp.iMvX, iHalfMvy - 1 - pMe->sMvp.iMvY ); | ||
| 835 | sParams.iLms[1] = COST_MVD( pMe->pMvdCost, iHalfMvx - pMe->sMvp.iMvX, iHalfMvy + 1 - pMe->sMvp.iMvY ); | ||
| 836 | sParams.iLms[2] = COST_MVD( pMe->pMvdCost, iHalfMvx - 1 - pMe->sMvp.iMvX, iHalfMvy - pMe->sMvp.iMvY ); | ||
| 837 | sParams.iLms[3] = COST_MVD( pMe->pMvdCost, iHalfMvx + 1 - pMe->sMvp.iMvX, iHalfMvy - pMe->sMvp.iMvY ); | ||
| 838 | } | ||
| 839 | MeRefineQuarPixel(pFunc, pMe, pMeRefine, iWidth, iHeight, &sParams, kiStrideEnc); | ||
| 840 | |||
| 841 | if(iBestCost > sParams.iBestCost) | ||
| 842 | { | ||
| 843 | pBestPredInter = pMeRefine->pQuarPixBest; | ||
| 844 | iBestCost = sParams.iBestCost; | ||
| 845 | } | ||
| 846 | iBestQuarPix = sParams.iBestQuarPix; | ||
| 847 | |||
| 848 | //update final best MV | ||
| 849 | pMe->sMv.iMvX = iHalfMvx + iMvQuarAddX[iBestQuarPix]; | ||
| 850 | pMe->sMv.iMvY = iHalfMvy + pMvQuarAddY[iBestQuarPix]; | ||
| 851 | pMe->uiSatdCost = iBestCost; | ||
| 852 | |||
| 853 | //No half or quarter pixel best, so do MC with integer pixel MV | ||
| 854 | if ( iBestHalfPix+iBestQuarPix == NO_BEST_FRAC_PIX ) | ||
| 855 | { | ||
| 856 | pBestPredInter = pRef; | ||
| 857 | iInterBlk4Stride = kiStrideRef; | ||
| 858 | } | ||
| 859 | if ( MB_WIDTH_LUMA == iWidth && MB_HEIGHT_LUMA == iHeight ) //P16x16 | ||
| 860 | { | ||
| 861 | pFunc->pfCopy16x16NotAligned( pMemPredInterMb, MB_WIDTH_LUMA, pBestPredInter, iInterBlk4Stride ); // dst can be align with 16 bytes, but not sure at pSrc, 12/29/2011 | ||
| 862 | } | ||
| 863 | else if ( MB_WIDTH_LUMA == iWidth && MB_HEIGHT_CHROMA == iHeight ) //P16x8 | ||
| 864 | { | ||
| 865 | pFunc->pfCopy16x8NotAligned( pMemPredInterMb, MB_WIDTH_LUMA, pBestPredInter, iInterBlk4Stride ); // dst can be align with 16 bytes, but not sure at pSrc, 12/29/2011 | ||
| 866 | } | ||
| 867 | else if ( MB_WIDTH_CHROMA == iWidth && MB_HEIGHT_LUMA == iHeight ) //P8x16 | ||
| 868 | { | ||
| 869 | pFunc->pfCopy8x16Aligned( pMemPredInterMb, MB_WIDTH_LUMA, pBestPredInter, iInterBlk4Stride ); | ||
| 870 | } | ||
| 871 | else //P8x8 | ||
| 872 | { | ||
| 873 | pFunc->pfCopy8x8Aligned( pMemPredInterMb, MB_WIDTH_LUMA, pBestPredInter, iInterBlk4Stride ); | ||
| 874 | } | ||
| 875 | } | ||
| 876 | |||
| 877 | void InitBlkStrideWithRef(int32_t* pBlkStride, const int32_t kiStrideRef) | ||
| 878 | { | ||
| 879 | static const uint8_t kuiStrideX[16] = | ||
| 880 | { | ||
| 881 | 0, 4 , 0, 4 , | ||
| 882 | 8, 12, 8, 12, | ||
| 883 | 0, 4 , 0, 4 , | ||
| 884 | 8, 12, 8, 12 | ||
| 885 | }; | ||
| 886 | static const uint8_t kuiStrideY[16] = | ||
| 887 | { | ||
| 888 | 0, 0, 4 , 4 , | ||
| 889 | 0, 0, 4 , 4 , | ||
| 890 | 8, 8, 12, 12, | ||
| 891 | 8, 8, 12, 12 | ||
| 892 | }; | ||
| 893 | int32_t i; | ||
| 894 | |||
| 895 | for (i = 0; i < 16; i+=4) | ||
| 896 | { | ||
| 897 | pBlkStride[i ] = kuiStrideX[i ] + kuiStrideY[i ] * kiStrideRef; | ||
| 898 | pBlkStride[i+1] = kuiStrideX[i+1] + kuiStrideY[i+1] * kiStrideRef; | ||
| 899 | pBlkStride[i+2] = kuiStrideX[i+2] + kuiStrideY[i+2] * kiStrideRef; | ||
| 900 | pBlkStride[i+3] = kuiStrideX[i+3] + kuiStrideY[i+3] * kiStrideRef; | ||
| 901 | } | ||
| 902 | } | ||
| 903 | |||
| 904 | /* | ||
| 905 | * iMvdSz = (648*2+1) or (972*2+1); | ||
| 906 | */ | ||
| 907 | void MvdCostInit( uint16_t* pMvdCostInter, const int32_t kiMvdSz ) | ||
| 908 | { | ||
| 909 | const int32_t kiSz = kiMvdSz >> 1; | ||
| 910 | uint16_t *pNegMvd = pMvdCostInter; | ||
| 911 | uint16_t *pPosMvd = pMvdCostInter+kiSz+1; | ||
| 912 | const int32_t *kpQpLambda= &g_kiQpCostTable[0]; | ||
| 913 | int32_t i,j; | ||
| 914 | |||
| 915 | for( i = 0; i < 52; ++ i ) | ||
| 916 | { | ||
| 917 | const uint16_t kiLambda = kpQpLambda[i]; | ||
| 918 | int32_t iNegSe = -kiSz; | ||
| 919 | int32_t iPosSe = 1; | ||
| 920 | |||
| 921 | for (j = 0; j < kiSz; j += 4) | ||
| 922 | { | ||
| 923 | *pNegMvd++ = kiLambda * BsSizeSE(iNegSe++); | ||
| 924 | *pNegMvd++ = kiLambda * BsSizeSE(iNegSe++); | ||
| 925 | *pNegMvd++ = kiLambda * BsSizeSE(iNegSe++); | ||
| 926 | *pNegMvd++ = kiLambda * BsSizeSE(iNegSe++); | ||
| 927 | |||
| 928 | *pPosMvd++ = kiLambda * BsSizeSE(iPosSe++); | ||
| 929 | *pPosMvd++ = kiLambda * BsSizeSE(iPosSe++); | ||
| 930 | *pPosMvd++ = kiLambda * BsSizeSE(iPosSe++); | ||
| 931 | *pPosMvd++ = kiLambda * BsSizeSE(iPosSe++); | ||
| 932 | } | ||
| 933 | *pNegMvd = kiLambda; | ||
| 934 | pNegMvd += kiSz+1; | ||
| 935 | pPosMvd += kiSz+1; | ||
| 936 | } | ||
| 937 | } | ||
| 938 | |||
| 939 | void PredictSad( int8_t* pRefIndexCache, int32_t* pSadCostCache, int32_t uiRef, int32_t * pSadPred ) | ||
| 940 | { | ||
| 941 | const int32_t kiRefB = pRefIndexCache[1];//top g_uiCache12_8x8RefIdx[0] - 4 | ||
| 942 | int32_t iRefC = pRefIndexCache[5];//top-right g_uiCache12_8x8RefIdx[0] - 2 | ||
| 943 | const int32_t kiRefA = pRefIndexCache[6];//left g_uiCache12_8x8RefIdx[0] - 1 | ||
| 944 | const int32_t kiSadB = pSadCostCache[1]; | ||
| 945 | int32_t iSadC = pSadCostCache[2]; | ||
| 946 | const int32_t kiSadA = pSadCostCache[3]; | ||
| 947 | |||
| 948 | int32_t iCount; | ||
| 949 | |||
| 950 | if( iRefC == REF_NOT_AVAIL ) | ||
| 951 | { | ||
| 952 | iRefC = pRefIndexCache[0];//top-left g_uiCache12_8x8RefIdx[0] - 4 - 1 | ||
| 953 | iSadC = pSadCostCache[0]; | ||
| 954 | } | ||
| 955 | |||
| 956 | if( kiRefB == REF_NOT_AVAIL && iRefC == REF_NOT_AVAIL && kiRefA != REF_NOT_AVAIL ) | ||
| 957 | { | ||
| 958 | * pSadPred = kiSadA; | ||
| 959 | } | ||
| 960 | else | ||
| 961 | { | ||
| 962 | iCount = (uiRef == kiRefA)<<MB_LEFT_BIT; | ||
| 963 | iCount |= (uiRef == kiRefB)<<MB_TOP_BIT; | ||
| 964 | iCount |= (uiRef == iRefC)<<MB_TOPRIGHT_BIT; | ||
| 965 | switch(iCount) | ||
| 966 | { | ||
| 967 | case LEFT_MB_POS:// A | ||
| 968 | *pSadPred = kiSadA; | ||
| 969 | break; | ||
| 970 | case TOP_MB_POS:// B | ||
| 971 | *pSadPred = kiSadB; | ||
| 972 | break; | ||
| 973 | case TOPRIGHT_MB_POS:// C or D | ||
| 974 | *pSadPred = iSadC; | ||
| 975 | break; | ||
| 976 | default: | ||
| 977 | *pSadPred = WELS_MEDIAN( kiSadA, kiSadB, iSadC ); | ||
| 978 | break; | ||
| 979 | } | ||
| 980 | } | ||
| 981 | |||
| 982 | #define REPLACE_SAD_MULTIPLY(x) ((x) - (x>>3) + (x >>5)) // it's 0.90625, very close with 0.9 | ||
| 983 | iCount = (*pSadPred)<<6; // here *64 will not overflow. SAD range 0~ 255*256(max 2^16), int32_t is enough | ||
| 984 | *pSadPred = (REPLACE_SAD_MULTIPLY(iCount) + 32)>>6; | ||
| 985 | #undef REPLACE_SAD_MULTIPLY | ||
| 986 | } | ||
| 987 | |||
| 988 | |||
| 989 | void PredictSadSkip( int8_t* pRefIndexCache, bool_t* pMbSkipCache, int32_t* pSadCostCache, int32_t uiRef, int32_t * iSadPredSkip ) | ||
| 990 | { | ||
| 991 | const int32_t kiRefB = pRefIndexCache[1];//top g_uiCache12_8x8RefIdx[0] - 4 | ||
| 992 | int32_t iRefC = pRefIndexCache[5];//top-right g_uiCache12_8x8RefIdx[0] - 2 | ||
| 993 | const int32_t kiRefA = pRefIndexCache[6];//left g_uiCache12_8x8RefIdx[0] - 1 | ||
| 994 | const int32_t kiSadB = (pMbSkipCache[1]==1 ? pSadCostCache[1] : 0); | ||
| 995 | int32_t iSadC = (pMbSkipCache[2]==1 ? pSadCostCache[2] : 0); | ||
| 996 | const int32_t kiSadA = (pMbSkipCache[3]==1 ? pSadCostCache[3] : 0); | ||
| 997 | int32_t iRefSkip = pMbSkipCache[2]; | ||
| 998 | |||
| 999 | int32_t iCount = 0; | ||
| 1000 | |||
| 1001 | if( iRefC == REF_NOT_AVAIL ) | ||
| 1002 | { | ||
| 1003 | iRefC = pRefIndexCache[0];//top-left g_uiCache12_8x8RefIdx[0] - 4 - 1 | ||
| 1004 | iSadC = (pMbSkipCache[0]==1 ? pSadCostCache[0] : 0); | ||
| 1005 | iRefSkip = pMbSkipCache[0]; | ||
| 1006 | } | ||
| 1007 | |||
| 1008 | if( kiRefB == REF_NOT_AVAIL && iRefC == REF_NOT_AVAIL && kiRefA != REF_NOT_AVAIL ) | ||
| 1009 | { | ||
| 1010 | * iSadPredSkip = kiSadA; | ||
| 1011 | } | ||
| 1012 | else | ||
| 1013 | { | ||
| 1014 | iCount = ((uiRef == kiRefA) && (pMbSkipCache[3]==1))<<MB_LEFT_BIT; | ||
| 1015 | iCount |= ((uiRef == kiRefB) && (pMbSkipCache[1]==1))<<MB_TOP_BIT; | ||
| 1016 | iCount |= ((uiRef == iRefC) && (iRefSkip==1))<<MB_TOPRIGHT_BIT; | ||
| 1017 | switch(iCount) | ||
| 1018 | { | ||
| 1019 | case LEFT_MB_POS:// A | ||
| 1020 | *iSadPredSkip = kiSadA; | ||
| 1021 | break; | ||
| 1022 | case TOP_MB_POS:// B | ||
| 1023 | *iSadPredSkip = kiSadB; | ||
| 1024 | break; | ||
| 1025 | case TOPRIGHT_MB_POS:// C or D | ||
| 1026 | *iSadPredSkip = iSadC; | ||
| 1027 | break; | ||
| 1028 | default: | ||
| 1029 | *iSadPredSkip = WELS_MEDIAN( kiSadA, kiSadB, iSadC ); | ||
| 1030 | break; | ||
| 1031 | } | ||
| 1032 | } | ||
| 1033 | } | ||
| 1034 | } | ||