1 /* 2 * Copyright (C) 2007-2008 ARM Limited 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 */ 17 /** 18 * 19 * File Name: omxVCM4P2_MotionEstimationMB.c 20 * OpenMAX DL: v1.0.2 21 * Revision: 9641 22 * Date: Thursday, February 7, 2008 23 * 24 * 25 * 26 * 27 * Description: 28 * Contains module for motion search 16x16 macroblock 29 * 30 */ 31 32 #include "omxtypes.h" 33 #include "armOMX.h" 34 #include "omxVC.h" 35 36 #include "armVC.h" 37 #include "armCOMM.h" 38 39 /** 40 * Function: armVCM4P2_BlockMatch_16x16 41 * 42 * Description: 43 * 16x16 block match wrapper function, calls omxVCM4P2_BlockMatch_Integer_16x16. 44 * If half pel search is enabled it also calls omxVCM4P2_BlockMatch_Half_16x16 45 * 46 * Remarks: 47 * 48 * Parameters: 49 * [in] pSrcRefBuf pointer to the reference Y plane; points to the reference MB that 50 * corresponds to the location of the current macroblock in the current 51 * plane. 52 * [in] srcRefStep width of the reference plane 53 * [in] pRefRect pointer to the valid rectangular in reference plane. Relative to image origin. 54 * It's not limited to the image boundary, but depended on the padding. For example, 55 * if you pad 4 pixels outside the image border, then the value for left border 56 * can be -4 57 * [in] pSrcCurrBuf pointer to the current macroblock extracted from original plane (linear array, 58 * 256 entries); must be aligned on an 16-byte boundary. 59 * [in] pCurrPointPos position of the current macroblock in the current plane 60 * [in] pSrcPreMV pointer to predicted motion vector; NULL indicates no predicted MV 61 * [in] pSrcPreSAD pointer to SAD associated with the predicted MV (referenced by pSrcPreMV); may be set to NULL if unavailable. 62 * [in] pMESpec vendor-specific motion estimation specification structure; must have been allocated 63 * and then initialized using omxVCM4P2_MEInit prior to calling the block matching 64 * function. 65 * [out] pDstMV pointer to estimated MV 66 * [out] pDstSAD pointer to minimum SAD 67 * * 68 * Return Value: 69 * OMX_Sts_NoErr - no error 70 * OMX_Sts_BadArgErr - bad arguments 71 * 72 */ 73 static OMXResult armVCM4P2_BlockMatch_16x16( 74 const OMX_U8 *pSrcRefBuf, 75 const OMX_INT srcRefStep, 76 const OMXRect *pRefRect, 77 const OMX_U8 *pSrcCurrBuf, 78 const OMXVCM4P2Coordinate *pCurrPointPos, 79 OMXVCMotionVector *pSrcPreMV, 80 OMX_INT *pSrcPreSAD, 81 void *pMESpec, 82 OMXVCMotionVector *pDstMV, 83 OMX_INT *pDstSAD 84 ) 85 { 86 OMXVCM4P2MEParams *pMEParams = (OMXVCM4P2MEParams *)pMESpec; 87 OMX_INT rndVal; 88 89 rndVal = pMEParams->rndVal; 90 91 omxVCM4P2_BlockMatch_Integer_16x16( 92 pSrcRefBuf, 93 srcRefStep, 94 pRefRect, 95 pSrcCurrBuf, 96 pCurrPointPos, 97 pSrcPreMV, 98 pSrcPreSAD, 99 pMEParams, 100 pDstMV, 101 pDstSAD); 102 103 if (pMEParams->halfPelSearchEnable) 104 { 105 omxVCM4P2_BlockMatch_Half_16x16( 106 pSrcRefBuf, 107 srcRefStep, 108 pRefRect, 109 pSrcCurrBuf, 110 pCurrPointPos, 111 rndVal, 112 pDstMV, 113 pDstSAD); 114 } 115 116 return OMX_Sts_NoErr; 117 } 118 119 /** 120 * Function: armVCM4P2_BlockMatch_8x8 121 * 122 * Description: 123 * 8x8 block match wrapper function, calls omxVCM4P2_BlockMatch_Integer_8x8. 124 * If half pel search is enabled it also calls omxVCM4P2_BlockMatch_Half_8x8 125 * 126 * Remarks: 127 * 128 * Parameters: 129 * [in] pSrcRefBuf pointer to the reference Y plane; points to the reference MB that 130 * corresponds to the location of the current macroblock in the current 131 * plane. 132 * [in] srcRefStep width of the reference plane 133 * [in] pRefRect pointer to the valid rectangular in reference plane. Relative to image origin. 134 * It's not limited to the image boundary, but depended on the padding. For example, 135 * if you pad 4 pixels outside the image border, then the value for left border 136 * can be -4 137 * [in] pSrcCurrBuf pointer to the current macroblock extracted from original plane (linear array, 138 * 256 entries); must be aligned on an 16-byte boundary. 139 * [in] pCurrPointPos position of the current macroblock in the current plane 140 * [in] pSrcPreMV pointer to predicted motion vector; NULL indicates no predicted MV 141 * [in] pSrcPreSAD pointer to SAD associated with the predicted MV (referenced by pSrcPreMV); may be set to NULL if unavailable. 142 * [in] pMESpec vendor-specific motion estimation specification structure; must have been allocated 143 * and then initialized using omxVCM4P2_MEInit prior to calling the block matching 144 * function. 145 * [out] pDstMV pointer to estimated MV 146 * [out] pDstSAD pointer to minimum SAD 147 * * 148 * Return Value: 149 * OMX_Sts_NoErr - no error 150 * OMX_Sts_BadArgErr - bad arguments 151 * 152 */ 153 static OMXResult armVCM4P2_BlockMatch_8x8( 154 const OMX_U8 *pSrcRefBuf, 155 OMX_INT srcRefStep, 156 const OMXRect *pRefRect, 157 const OMX_U8 *pSrcCurrBuf, 158 const OMXVCM4P2Coordinate *pCurrPointPos, 159 OMXVCMotionVector *pSrcPreMV, 160 OMX_INT *pSrcPreSAD, 161 void *pMESpec, 162 OMXVCMotionVector *pSrcDstMV, 163 OMX_INT *pDstSAD 164 ) 165 { 166 OMXVCM4P2MEParams *pMEParams = (OMXVCM4P2MEParams *)pMESpec; 167 OMX_INT rndVal; 168 169 rndVal = pMEParams->rndVal; 170 171 omxVCM4P2_BlockMatch_Integer_8x8( 172 pSrcRefBuf, 173 srcRefStep, 174 pRefRect, 175 pSrcCurrBuf, 176 pCurrPointPos, 177 pSrcPreMV, 178 pSrcPreSAD, 179 pMEParams, 180 pSrcDstMV, 181 pDstSAD); 182 183 if (pMEParams->halfPelSearchEnable) 184 { 185 omxVCM4P2_BlockMatch_Half_8x8( 186 pSrcRefBuf, 187 srcRefStep, 188 pRefRect, 189 pSrcCurrBuf, 190 pCurrPointPos, 191 rndVal, 192 pSrcDstMV, 193 pDstSAD); 194 } 195 196 return OMX_Sts_NoErr; 197 } 198 199 200 /** 201 * Function: omxVCM4P2_MotionEstimationMB (6.2.4.3.1) 202 * 203 * Description: 204 * Performs motion search for a 16x16 macroblock. Selects best motion search 205 * strategy from among inter-1MV, inter-4MV, and intra modes. Supports 206 * integer and half pixel resolution. 207 * 208 * Input Arguments: 209 * 210 * pSrcCurrBuf - pointer to the top-left corner of the current MB in the 211 * original picture plane; must be aligned on a 16-byte boundary. 212 * The function does not expect source data outside the region 213 * bounded by the MB to be available; for example it is not 214 * necessary for the caller to guarantee the availability of 215 * pSrcCurrBuf[-SrcCurrStep], i.e., the row of pixels above the MB 216 * to be processed. 217 * srcCurrStep - width of the original picture plane, in terms of full 218 * pixels; must be a multiple of 16. 219 * pSrcRefBuf - pointer to the reference Y plane; points to the reference 220 * plane location corresponding to the location of the current 221 * macroblock in the current plane; must be aligned on a 16-byte 222 * boundary. 223 * srcRefStep - width of the reference picture plane, in terms of full 224 * pixels; must be a multiple of 16. 225 * pRefRect - reference plane valid region rectangle, specified relative to 226 * the image origin 227 * pCurrPointPos - position of the current macroblock in the current plane 228 * pMESpec - pointer to the vendor-specific motion estimation specification 229 * structure; must be allocated and then initialized using 230 * omxVCM4P2_MEInit prior to calling this function. 231 * pMBInfo - array, of dimension four, containing pointers to information 232 * associated with four nearby MBs: 233 * - pMBInfo[0] - pointer to left MB information 234 * - pMBInfo[1] - pointer to top MB information 235 * - pMBInfo[2] - pointer to top-left MB information 236 * - pMBInfo[3] - pointer to top-right MB information 237 * Any pointer in the array may be set equal to NULL if the 238 * corresponding MB doesn't exist. For each MB, the following structure 239 * members are used: 240 * - mbType - macroblock type, either OMX_VC_INTRA, OMX_VC_INTER, or 241 * OMX_VC_INTER4V 242 * - pMV0[2][2] - estimated motion vectors; represented 243 * in 1/2 pixel units 244 * - sliceID - number of the slice to which the MB belongs 245 * pSrcDstMBCurr - pointer to information structure for the current MB. 246 * The following entries should be set prior to calling the 247 * function: sliceID - the number of the slice the to which the 248 * current MB belongs. The structure elements cbpy and cbpc are 249 * ignored. 250 * 251 * Output Arguments: 252 * 253 * pSrcDstMBCurr - pointer to updated information structure for the current 254 * MB after MB-level motion estimation has been completed. The 255 * following structure members are updated by the ME function: 256 * - mbType - macroblock type: OMX_VC_INTRA, OMX_VC_INTER, or 257 * OMX_VC_INTER4V. 258 * - pMV0[2][2] - estimated motion vectors; represented in 259 * terms of 1/2 pel units. 260 * - pMVPred[2][2] - predicted motion vectors; represented 261 * in terms of 1/2 pel units. 262 * The structure members cbpy and cbpc are not updated by the function. 263 * pDstSAD - pointer to the minimum SAD for INTER1V, or sum of minimum SADs 264 * for INTER4V 265 * pDstBlockSAD - pointer to an array of SAD values for each of the four 266 * 8x8 luma blocks in the MB. The block SADs are in scan order for 267 * each MB. 268 * 269 * Return Value: 270 * 271 * OMX_Sts_NoErr - no error 272 * OMX_Sts_BadArgErr - bad arguments. Returned if one or more of the 273 * following conditions is true: 274 * - at least one of the following pointers is NULL: pSrcCurrBuf, 275 * pSrcRefBuf, pRefRect, pCurrPointPos, pMBInter, pMBIntra, 276 * pSrcDstMBCurr, or pDstSAD. 277 * 278 */ 279 280 OMXResult omxVCM4P2_MotionEstimationMB ( 281 const OMX_U8 *pSrcCurrBuf, 282 OMX_S32 srcCurrStep, 283 const OMX_U8 *pSrcRefBuf, 284 OMX_S32 srcRefStep, 285 const OMXRect*pRefRect, 286 const OMXVCM4P2Coordinate *pCurrPointPos, 287 void *pMESpec, 288 const OMXVCM4P2MBInfoPtr *pMBInfo, 289 OMXVCM4P2MBInfo *pSrcDstMBCurr, 290 OMX_U16 *pDstSAD, 291 OMX_U16 *pDstBlockSAD 292 ) 293 { 294 295 OMX_INT intraSAD, average, count, index, x, y; 296 OMXVCMotionVector dstMV16x16; 297 OMX_INT dstSAD16x16; 298 OMX_INT dstSAD8x8; 299 OMXVCM4P2MEParams *pMEParams; 300 OMXVCM4P2Coordinate TempCurrPointPos; 301 OMXVCM4P2Coordinate *pTempCurrPointPos; 302 OMX_U8 aTempSrcCurrBuf[271]; 303 OMX_U8 *pTempSrcCurrBuf; 304 OMX_U8 *pDst; 305 OMX_U8 aDst[71]; 306 OMX_S32 dstStep = 8; 307 OMX_INT predictType; 308 OMX_S32 Sad; 309 const OMX_U8 *pTempSrcRefBuf; 310 OMXVCMotionVector* pSrcCandMV1[4]; 311 OMXVCMotionVector* pSrcCandMV2[4]; 312 OMXVCMotionVector* pSrcCandMV3[4]; 313 314 /* Argument error checks */ 315 armRetArgErrIf(!armIs16ByteAligned(pSrcCurrBuf), OMX_Sts_BadArgErr); 316 armRetArgErrIf(!armIs16ByteAligned(pSrcRefBuf), OMX_Sts_BadArgErr); 317 armRetArgErrIf(((srcCurrStep % 16) || (srcRefStep % 16)), OMX_Sts_BadArgErr); 318 armRetArgErrIf(pSrcCurrBuf == NULL, OMX_Sts_BadArgErr); 319 armRetArgErrIf(pSrcRefBuf == NULL, OMX_Sts_BadArgErr); 320 armRetArgErrIf(pRefRect == NULL, OMX_Sts_BadArgErr); 321 armRetArgErrIf(pCurrPointPos == NULL, OMX_Sts_BadArgErr); 322 armRetArgErrIf(pSrcDstMBCurr == NULL, OMX_Sts_BadArgErr); 323 armRetArgErrIf(pDstSAD == NULL, OMX_Sts_BadArgErr); 324 325 326 pTempCurrPointPos = &(TempCurrPointPos); 327 pTempSrcCurrBuf = armAlignTo16Bytes(aTempSrcCurrBuf); 328 pMEParams = (OMXVCM4P2MEParams *)pMESpec; 329 pTempCurrPointPos->x = pCurrPointPos->x; 330 pTempCurrPointPos->y = pCurrPointPos->y; 331 pSrcDstMBCurr->mbType = OMX_VC_INTER; 332 333 /* Preparing a linear buffer for block match */ 334 for (y = 0, index = count = 0; y < 16; y++, index += srcCurrStep - 16) 335 { 336 for(x = 0; x < 16; x++, count++, index++) 337 { 338 pTempSrcCurrBuf[count] = pSrcCurrBuf[index]; 339 } 340 } 341 for(y = 0, index = 0; y < 2; y++) 342 { 343 for(x = 0; x < 2; x++,index++) 344 { 345 if((pMBInfo[0] != NULL) && (pMBInfo[0]->mbType != OMX_VC_INTRA)) 346 { 347 pSrcCandMV1[index] = &(pMBInfo[0]->pMV0[y][x]); 348 } 349 else 350 { 351 pSrcCandMV1[index] = NULL; 352 } 353 if((pMBInfo[1] != NULL) && (pMBInfo[1]->mbType != OMX_VC_INTRA)) 354 { 355 pSrcCandMV2[index] = &(pMBInfo[1]->pMV0[y][x]); 356 } 357 else 358 { 359 pSrcCandMV2[index] = NULL; 360 } 361 if((pMBInfo[3] != NULL) && (pMBInfo[3]->mbType != OMX_VC_INTRA)) 362 { 363 pSrcCandMV3[index] = &(pMBInfo[3]->pMV0[y][x]); 364 } 365 else 366 { 367 pSrcCandMV3[index] = NULL; 368 } 369 } 370 } 371 /* Calculating SAD at MV(0,0) */ 372 armVCCOMM_SAD(pTempSrcCurrBuf, 373 16, 374 pSrcRefBuf, 375 srcRefStep, 376 &Sad, 377 16, 378 16); 379 *pDstSAD = Sad; 380 381 /* Mode decision for NOT_CODED MB */ 382 if(*pDstSAD == 0) 383 { 384 pSrcDstMBCurr->pMV0[0][0].dx = 0; 385 pSrcDstMBCurr->pMV0[0][0].dy = 0; 386 *pDstSAD = 0; 387 return OMX_Sts_NoErr; 388 } 389 390 omxVCM4P2_FindMVpred( 391 &(pSrcDstMBCurr->pMV0[0][0]), 392 pSrcCandMV1[0], 393 pSrcCandMV2[0], 394 pSrcCandMV3[0], 395 &(pSrcDstMBCurr->pMVPred[0][0]), 396 NULL, 397 0); 398 399 /* Inter 1 MV */ 400 armVCM4P2_BlockMatch_16x16( 401 pSrcRefBuf, 402 srcRefStep, 403 pRefRect, 404 pTempSrcCurrBuf, 405 pCurrPointPos, 406 &(pSrcDstMBCurr->pMVPred[0][0]), 407 NULL, 408 pMEParams, 409 &dstMV16x16, 410 &dstSAD16x16); 411 412 /* Initialize all with 1 MV values */ 413 pSrcDstMBCurr->pMV0[0][0].dx = dstMV16x16.dx; 414 pSrcDstMBCurr->pMV0[0][0].dy = dstMV16x16.dy; 415 pSrcDstMBCurr->pMV0[0][1].dx = dstMV16x16.dx; 416 pSrcDstMBCurr->pMV0[0][1].dy = dstMV16x16.dy; 417 pSrcDstMBCurr->pMV0[1][0].dx = dstMV16x16.dx; 418 pSrcDstMBCurr->pMV0[1][0].dy = dstMV16x16.dy; 419 pSrcDstMBCurr->pMV0[1][1].dx = dstMV16x16.dx; 420 pSrcDstMBCurr->pMV0[1][1].dy = dstMV16x16.dy; 421 422 *pDstSAD = dstSAD16x16; 423 424 if (pMEParams->searchEnable8x8) 425 { 426 /* Inter 4MV */ 427 armVCM4P2_BlockMatch_8x8 (pSrcRefBuf, 428 srcRefStep, pRefRect, 429 pTempSrcCurrBuf, pTempCurrPointPos, 430 &(pSrcDstMBCurr->pMVPred[0][0]), NULL, 431 pMEParams, &(pSrcDstMBCurr->pMV0[0][0]), 432 &dstSAD8x8 433 ); 434 pDstBlockSAD[0] = dstSAD8x8; 435 *pDstSAD = dstSAD8x8; 436 pTempCurrPointPos->x += 8; 437 pSrcRefBuf += 8; 438 omxVCM4P2_FindMVpred( 439 &(pSrcDstMBCurr->pMV0[0][1]), 440 pSrcCandMV1[1], 441 pSrcCandMV2[1], 442 pSrcCandMV3[1], 443 &(pSrcDstMBCurr->pMVPred[0][1]), 444 NULL, 445 1); 446 447 armVCM4P2_BlockMatch_8x8 (pSrcRefBuf, 448 srcRefStep, pRefRect, 449 pTempSrcCurrBuf, pTempCurrPointPos, 450 &(pSrcDstMBCurr->pMVPred[0][1]), NULL, 451 pMEParams, &(pSrcDstMBCurr->pMV0[0][1]), 452 &dstSAD8x8 453 ); 454 pDstBlockSAD[1] = dstSAD8x8; 455 *pDstSAD += dstSAD8x8; 456 pTempCurrPointPos->x -= 8; 457 pTempCurrPointPos->y += 8; 458 pSrcRefBuf += (srcRefStep * 8) - 8; 459 460 omxVCM4P2_FindMVpred( 461 &(pSrcDstMBCurr->pMV0[1][0]), 462 pSrcCandMV1[2], 463 pSrcCandMV2[2], 464 pSrcCandMV3[2], 465 &(pSrcDstMBCurr->pMVPred[1][0]), 466 NULL, 467 2); 468 armVCM4P2_BlockMatch_8x8 (pSrcRefBuf, 469 srcRefStep, pRefRect, 470 pTempSrcCurrBuf, pTempCurrPointPos, 471 &(pSrcDstMBCurr->pMVPred[1][0]), NULL, 472 pMEParams, &(pSrcDstMBCurr->pMV0[1][0]), 473 &dstSAD8x8 474 ); 475 pDstBlockSAD[2] = dstSAD8x8; 476 *pDstSAD += dstSAD8x8; 477 pTempCurrPointPos->x += 8; 478 pSrcRefBuf += 8; 479 omxVCM4P2_FindMVpred( 480 &(pSrcDstMBCurr->pMV0[1][1]), 481 pSrcCandMV1[3], 482 pSrcCandMV2[3], 483 pSrcCandMV3[3], 484 &(pSrcDstMBCurr->pMVPred[1][1]), 485 NULL, 486 3); 487 armVCM4P2_BlockMatch_8x8 (pSrcRefBuf, 488 srcRefStep, pRefRect, 489 pTempSrcCurrBuf, pTempCurrPointPos, 490 &(pSrcDstMBCurr->pMVPred[1][1]), NULL, 491 pMEParams, &(pSrcDstMBCurr->pMV0[1][1]), 492 &dstSAD8x8 493 ); 494 pDstBlockSAD[3] = dstSAD8x8; 495 *pDstSAD += dstSAD8x8; 496 497 498 /* Checking if 4MV is equal to 1MV */ 499 if ( 500 (pSrcDstMBCurr->pMV0[0][0].dx != dstMV16x16.dx) || 501 (pSrcDstMBCurr->pMV0[0][0].dy != dstMV16x16.dy) || 502 (pSrcDstMBCurr->pMV0[0][1].dx != dstMV16x16.dx) || 503 (pSrcDstMBCurr->pMV0[0][1].dy != dstMV16x16.dy) || 504 (pSrcDstMBCurr->pMV0[1][0].dx != dstMV16x16.dx) || 505 (pSrcDstMBCurr->pMV0[1][0].dy != dstMV16x16.dy) || 506 (pSrcDstMBCurr->pMV0[1][1].dx != dstMV16x16.dx) || 507 (pSrcDstMBCurr->pMV0[1][1].dy != dstMV16x16.dy) 508 ) 509 { 510 /* select the 4 MV */ 511 pSrcDstMBCurr->mbType = OMX_VC_INTER4V; 512 } 513 } 514 515 /* finding the error in intra mode */ 516 for (count = 0, average = 0; count < 256 ; count++) 517 { 518 average = average + pTempSrcCurrBuf[count]; 519 } 520 average = average/256; 521 522 intraSAD = 0; 523 524 /* Intra SAD calculation */ 525 for (count = 0; count < 256 ; count++) 526 { 527 intraSAD += armAbs ((pTempSrcCurrBuf[count]) - (average)); 528 } 529 530 /* Using the MPEG4 VM formula for intra/inter mode decision 531 Var < (SAD - 2*NB) where NB = N^2 is the number of pixels 532 of the macroblock.*/ 533 534 if (intraSAD <= (*pDstSAD - 512)) 535 { 536 pSrcDstMBCurr->mbType = OMX_VC_INTRA; 537 pSrcDstMBCurr->pMV0[0][0].dx = 0; 538 pSrcDstMBCurr->pMV0[0][0].dy = 0; 539 *pDstSAD = intraSAD; 540 pDstBlockSAD[0] = 0xFFFF; 541 pDstBlockSAD[1] = 0xFFFF; 542 pDstBlockSAD[2] = 0xFFFF; 543 pDstBlockSAD[3] = 0xFFFF; 544 } 545 546 if(pSrcDstMBCurr->mbType == OMX_VC_INTER) 547 { 548 pTempSrcRefBuf = pSrcRefBuf + (srcRefStep * dstMV16x16.dy) + dstMV16x16.dx; 549 550 if((dstMV16x16.dx & 0x1) && (dstMV16x16.dy & 0x1)) 551 { 552 predictType = OMX_VC_HALF_PIXEL_XY; 553 } 554 else if(dstMV16x16.dx & 0x1) 555 { 556 predictType = OMX_VC_HALF_PIXEL_X; 557 } 558 else if(dstMV16x16.dy & 0x1) 559 { 560 predictType = OMX_VC_HALF_PIXEL_Y; 561 } 562 else 563 { 564 predictType = OMX_VC_INTEGER_PIXEL; 565 } 566 567 pDst = armAlignTo8Bytes(&(aDst[0])); 568 /* Calculating Block SAD at MV(dstMV16x16.dx,dstMV16x16.dy) */ 569 /* Block 0 */ 570 omxVCM4P2_MCReconBlock(pTempSrcRefBuf, 571 srcRefStep, 572 NULL, 573 pDst, 574 dstStep, 575 predictType, 576 pMEParams->rndVal); 577 578 armVCCOMM_SAD(pTempSrcCurrBuf, 579 16, 580 pDst, 581 dstStep, 582 &Sad, 583 8, 584 8); 585 pDstBlockSAD[0] = Sad; 586 587 /* Block 1 */ 588 omxVCM4P2_MCReconBlock(pTempSrcRefBuf + 8, 589 srcRefStep, 590 NULL, 591 pDst, 592 dstStep, 593 predictType, 594 pMEParams->rndVal); 595 596 armVCCOMM_SAD(pTempSrcCurrBuf + 8, 597 16, 598 pDst, 599 dstStep, 600 &Sad, 601 8, 602 8); 603 pDstBlockSAD[1] = Sad; 604 605 /* Block 2 */ 606 omxVCM4P2_MCReconBlock(pTempSrcRefBuf + (srcRefStep*8), 607 srcRefStep, 608 NULL, 609 pDst, 610 dstStep, 611 predictType, 612 pMEParams->rndVal); 613 614 armVCCOMM_SAD(pTempSrcCurrBuf + (16*8), 615 16, 616 pDst, 617 dstStep, 618 &Sad, 619 8, 620 8); 621 pDstBlockSAD[2] = Sad; 622 623 /* Block 3 */ 624 omxVCM4P2_MCReconBlock(pTempSrcRefBuf + (srcRefStep*8) + 8, 625 srcRefStep, 626 NULL, 627 pDst, 628 dstStep, 629 predictType, 630 pMEParams->rndVal); 631 632 armVCCOMM_SAD(pTempSrcCurrBuf + (16*8) + 8, 633 16, 634 pDst, 635 dstStep, 636 &Sad, 637 8, 638 8); 639 pDstBlockSAD[3] = Sad; 640 } 641 return OMX_Sts_NoErr; 642 } 643 644 /* End of file */ 645 646