1 /** x 2 * 3 * File Name: omxVCM4P10_MotionEstimationMB.c 4 * OpenMAX DL: v1.0.2 5 * Revision: 9641 6 * Date: Thursday, February 7, 2008 7 * 8 * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved. 9 * 10 * 11 * Description: 12 * This function perform MB level motion estimation 13 * 14 */ 15 16 #include "omxtypes.h" 17 #include "armOMX.h" 18 #include "omxVC.h" 19 20 #include "armCOMM.h" 21 #include "armVC.h" 22 23 #define ARM_VCM4P10_MAX_FRAMES (15) 24 #define ARM_VCM4P10_MAX_4x4_SAD (0xffff) 25 #define ARM_VCM4P10_MAX_MODE_VALUE (0xffffffff) 26 #define ARM_VCM4P10_MAX_MODES (16) 27 #define ARM_VCM4P10_MB_BLOCK_SIZE (16) 28 #define ARM_VCM4P10_MEDIAN(a,b,c) (a>b?a>c?b>c?b:c:a:b>c?a>c?a:c:b) 29 #define ARM_VCM4P10_SHIFT_QP (12) 30 31 #define ARM_VCM4P10_MVPRED_MEDIAN (0) 32 #define ARM_VCM4P10_MVPRED_L (1) 33 #define ARM_VCM4P10_MVPRED_U (2) 34 #define ARM_VCM4P10_MVPRED_UR (3) 35 36 #define ARM_VCM4P10_MB_BLOCK_SIZE (16) 37 #define ARM_VCM4P10_BLOCK_SIZE (4) 38 #define ARM_VCM4P10_MAX_COST (1 << 30) 39 #define ARM_VCM4P10_INVALID_BLOCK (-2) 40 41 42 /** 43 * Function: armVCM4P10_CalculateBlockSAD 44 * 45 * Description: 46 * Calculate SAD value for the selected MB encoding mode and update 47 * pDstBlockSAD parameter. These SAD values are calculated 4x4 blocks at 48 * a time and in the scan order. 49 * 50 * Remarks: 51 * 52 * Parameters: 53 * [in] pSrcMBInfo - 54 * [in] pSrcCurrBuf - 55 * [in] SrcCurrStep - 56 * [in] pSrcRefBufList- 57 * [in] SrcRefStep - 58 * [in] pSrcRecBuf - 59 * [in] SrcRecStep - 60 * [in] pRefRect - 61 * [in] pCurrPointPos - 62 * [in] Lambda - 63 * [in] pMESpec - 64 * [in] pMBInter - 65 * [in] pMBIntra - 66 * [out] pDstBlockSAD - pointer to 16 element array for SAD corresponding to 4x4 blocks 67 * Return Value: 68 * None 69 * 70 */ 71 72 static OMXResult armVCM4P10_CalculateBlockSAD( 73 OMXVCM4P10MBInfo *pSrcMBInfo, 74 const OMX_U8 *pSrcCurrBuf, 75 OMX_S32 SrcCurrStep, 76 const OMX_U8 *pSrcRefBufList[ARM_VCM4P10_MAX_FRAMES], 77 OMX_S32 SrcRefStep, 78 const OMX_U8 *pSrcRecBuf, 79 OMX_S32 SrcRecStep, 80 const OMXRect *pRefRect, 81 const OMXVCM4P2Coordinate *pCurrPointPos, 82 const OMXVCM4P10MBInfoPtr *pMBInter, 83 const OMXVCM4P10MBInfoPtr *pMBIntra, 84 OMX_U16 *pDstBlockSAD) 85 { 86 OMX_INT InvalidSAD = 0; 87 OMX_INT i; 88 89 OMX_U8 Buffer [16*16 + 15]; 90 OMX_U8 *pTempDstBuf; 91 OMX_S32 TempDstStep; 92 OMX_U8 *pTempRefBuf; 93 OMX_S32 TempRefStep; 94 95 /* Temporary buffer to store the predicted mb coefficients */ 96 pTempDstBuf = armAlignTo16Bytes(Buffer); 97 TempDstStep = 16; 98 99 /* Update pDstBlockSAD if MB is a valid type */ 100 if (pSrcMBInfo) 101 { 102 OMX_U32 Width=0, Height=0, MaxXPart, MaxYPart,MaxSubXPart,MaxSubYPart; 103 104 /* Depending on type of MB, do prediction and fill temp buffer */ 105 switch (pSrcMBInfo->mbType) 106 { 107 case OMX_VC_P_16x16: 108 Width = 16; 109 Height = 16; 110 break; 111 case OMX_VC_P_16x8: 112 Width = 16; 113 Height = 8; 114 break; 115 case OMX_VC_P_8x16: 116 Width = 8; 117 Height = 16; 118 break; 119 case OMX_VC_P_8x8: 120 Width = 8; 121 Height = 8; 122 break; 123 case OMX_VC_INTRA_4x4: 124 { 125 /* Create predicted MB Intra4x4 mode */ 126 OMX_S32 PredIntra4x4Mode [5][9]; 127 OMX_S32 x, y, Block8x8, Block4x4, BlockX, BlockY; 128 OMX_U8 pSrcYBuff [(16*3)*(16*2)]; 129 OMX_U8 *pSrcY; 130 OMX_S32 StepSrcY; 131 OMX_S32 availability; 132 133 for (y = 0; y < 5; y++) 134 { 135 for (x = 0; x < 9; x++) 136 { 137 /* 138 * Initialize with value of ARM_VCM4P10_INVALID_BLOCK, to mean this 139 * 4x4 block is not available 140 */ 141 PredIntra4x4Mode [y][x] = ARM_VCM4P10_INVALID_BLOCK; 142 } 143 } 144 145 /* Replace ARM_VCM4P10_INVALID_BLOCK value with available MBs values*/ 146 for (x = 0; x < 4; x++) 147 { 148 /* Store values of b0, b1, b2, b3 */ 149 if (pMBIntra[1] != NULL) 150 { 151 PredIntra4x4Mode [0][x + 1] = 152 pMBIntra[1]->pIntra4x4PredMode[3*4 + x]; 153 } 154 155 /* Store values of d0, d1, d2, d3 */ 156 if (pMBIntra[3] != NULL) 157 { 158 PredIntra4x4Mode [0][x + 5] = 159 pMBIntra[3]->pIntra4x4PredMode[3*4 + x]; 160 } 161 } 162 163 /* Store values of c3 */ 164 if (pMBIntra[2] != NULL) 165 { 166 PredIntra4x4Mode [0][0] = pMBIntra[2]->pIntra4x4PredMode[15]; 167 } 168 169 for (y = 0; y < 4; y++) 170 { 171 /* Store values of a0, a1, a2, a3 */ 172 if (pMBIntra[0] != NULL) 173 { 174 PredIntra4x4Mode [y + 1][0] = 175 pMBIntra[0]->pIntra4x4PredMode[y*4 + 3]; 176 } 177 } 178 179 /* 180 * Update neighbouring Pred mode array which will be used for 181 * prediction of Intra4x4 modes. 182 */ 183 184 pSrcY = pSrcYBuff; 185 StepSrcY = 16 * 3; 186 for (y = 0; y < (16 * 2); y++) 187 { 188 for (x = 0; x < (16 * 3); x++) 189 { 190 pSrcY [StepSrcY * y + x] = 191 pSrcRecBuf [SrcRecStep * (y - 16) + x - 16]; 192 } 193 } 194 195 196 /* for each 8x8 block */ 197 for (Block8x8 = 0; Block8x8 < 4; Block8x8++) 198 { 199 /* for each 4x4 block inside 8x8 block */ 200 for (Block4x4 = 0; Block4x4 < 4; Block4x4++) 201 { 202 /* Get block cordinates from 8x8 block index and 4x4 block index */ 203 BlockX = ((Block8x8 & 1) << 1) + (Block4x4 & 1); 204 BlockY = ((Block8x8 >> 1) << 1) + (Block4x4 >> 1); 205 206 /* Add offset to point to start of current MB in the array pIntra4x4PredMode */ 207 x = BlockX + 1; 208 y = BlockY + 1; 209 210 availability = 0; 211 212 /* Check for availability of LEFT Block */ 213 if (PredIntra4x4Mode [y][x - 1] != ARM_VCM4P10_INVALID_BLOCK) 214 { 215 availability |= OMX_VC_LEFT; 216 } 217 218 /* Check for availability of UPPER Block */ 219 if (PredIntra4x4Mode [y - 1][x] != ARM_VCM4P10_INVALID_BLOCK) 220 { 221 availability |= OMX_VC_UPPER; 222 } 223 224 /* Check for availability of UPPER LEFT Block */ 225 if (PredIntra4x4Mode [y - 1][x - 1] != ARM_VCM4P10_INVALID_BLOCK) 226 { 227 availability |= OMX_VC_UPPER_LEFT; 228 } 229 230 PredIntra4x4Mode [y][x] = pSrcMBInfo->pIntra4x4PredMode[BlockY*4+BlockX]; 231 x = BlockX * 4; 232 y = BlockY * 4; 233 234 pSrcY = pSrcYBuff + 16 * StepSrcY + 16 + y * StepSrcY + x; 235 236 omxVCM4P10_PredictIntra_4x4( 237 pSrcY - 1, 238 pSrcY - StepSrcY, 239 pSrcY - StepSrcY - 1, 240 pTempDstBuf + x + y * TempDstStep, 241 StepSrcY, 242 TempDstStep, 243 pSrcMBInfo->pIntra4x4PredMode[BlockY*4+BlockX], 244 availability); 245 246 for (BlockY=0;BlockY<4;BlockY++) 247 { 248 for(BlockX=0;BlockX<4;BlockX++) 249 { 250 pSrcY [BlockY * StepSrcY + BlockX] = 251 (OMX_U8)(*(pTempDstBuf + x + y * TempDstStep + BlockY * TempDstStep + BlockX)); 252 } 253 } 254 255 } 256 } 257 break; 258 } 259 case OMX_VC_INTRA_16x16: 260 { 261 OMX_U32 MBPosX = pCurrPointPos->x >> 4; 262 OMX_U32 MBPosY = pCurrPointPos->y >> 4; 263 OMX_U32 availability = 0; 264 265 /* Check for availability of LEFT MB */ 266 if ((MBPosX != 0) && (pMBIntra [0] != 0 || pMBInter [0] != 0)) 267 { 268 availability |= OMX_VC_LEFT; 269 } 270 271 /* Check for availability of UP MB */ 272 if ((MBPosY != 0) && (pMBIntra [1] != 0 || pMBInter [1] != 0)) 273 { 274 availability |= OMX_VC_UPPER; 275 } 276 277 /* Check for availability of UP-LEFT MB */ 278 if ((MBPosX > 0) && (MBPosY > 0) && 279 (pMBIntra [2] != 0 || pMBInter [2] != 0)) 280 { 281 availability |= OMX_VC_UPPER_LEFT; 282 } 283 284 omxVCM4P10_PredictIntra_16x16( 285 pSrcRecBuf - 1, 286 pSrcRecBuf - SrcRecStep, 287 pSrcRecBuf - SrcRecStep - 1, 288 pTempDstBuf, 289 SrcRecStep, 290 TempDstStep, 291 pSrcMBInfo->Intra16x16PredMode, 292 availability); 293 294 break; 295 } 296 297 case OMX_VC_INTER_SKIP: 298 case OMX_VC_PREF0_8x8: 299 case OMX_VC_INTRA_PCM: 300 default: 301 /* These cases will update pDstBlockSAD with MAX value */ 302 InvalidSAD = 1; 303 break; 304 } 305 306 /* INTER MB */ 307 if ((pSrcMBInfo->mbType == OMX_VC_P_16x16) || 308 (pSrcMBInfo->mbType == OMX_VC_P_8x16) || 309 (pSrcMBInfo->mbType == OMX_VC_P_16x8) || 310 (pSrcMBInfo->mbType == OMX_VC_P_8x8)) 311 { 312 const OMX_U8 *pTempSrcBuf; 313 OMX_S32 TempSrcStep; 314 OMX_S32 mvx,mvy; 315 OMX_U32 PartX, PartY, SubPartX, SubPartY; 316 317 TempSrcStep = SrcRefStep; 318 319 MaxXPart = 16/Width; 320 MaxYPart = 16/Height; 321 322 323 for (PartY = 0; PartY < MaxYPart; PartY++) 324 { 325 for (PartX = 0; PartX < MaxXPart; PartX++) 326 { 327 328 pTempSrcBuf = pSrcRefBufList[pSrcMBInfo->pRefL0Idx[PartY * 2 + PartX]]; 329 330 if (MaxXPart == 2 && MaxYPart == 2) 331 { 332 switch (pSrcMBInfo->subMBType[PartY*2+PartX]) 333 { 334 case OMX_VC_SUB_P_8x8: 335 Width = 8; 336 Height = 8; 337 break; 338 case OMX_VC_SUB_P_8x4: 339 Width = 8; 340 Height = 4; 341 break; 342 case OMX_VC_SUB_P_4x8: 343 Width = 4; 344 Height = 8; 345 break; 346 case OMX_VC_SUB_P_4x4: 347 Width = 4; 348 Height = 4; 349 break; 350 default: 351 /* Default */ 352 Width = 4; 353 Height = 4; 354 break; 355 } 356 357 MaxSubXPart = 8/Width; 358 MaxSubYPart = 8/Height; 359 360 for (SubPartY = 0; SubPartY < MaxSubYPart; SubPartY++) 361 { 362 for (SubPartX = 0; SubPartX < MaxSubXPart; SubPartX++) 363 { 364 mvx = pSrcMBInfo->pMV0 [2*PartY + SubPartY][2*PartX + SubPartX].dx; 365 mvy = pSrcMBInfo->pMV0 [2*PartY + SubPartY][2*PartX + SubPartX].dy; 366 armVCM4P10_Interpolate_Luma( 367 pTempSrcBuf + (8*PartX + 4*SubPartX + (mvx/4)) + (8*PartY + 4*SubPartY + (mvy/4)) * TempSrcStep, 368 TempSrcStep, 369 pTempDstBuf + (8*PartX + 4*SubPartX) + (8*PartY + 4*SubPartY) * TempDstStep, 370 TempDstStep, 371 Width, 372 Height, 373 mvx & 3, 374 mvy & 3 375 ); 376 } 377 } 378 } 379 else 380 { 381 382 mvx = pSrcMBInfo->pMV0 [2*PartY][2*PartX].dx; 383 mvy = pSrcMBInfo->pMV0 [2*PartY][2*PartX].dy; 384 armVCM4P10_Interpolate_Luma( 385 pTempSrcBuf + (8*PartX + (mvx/4)) + (8*PartY + (mvy/4)) * TempSrcStep, 386 TempSrcStep, 387 pTempDstBuf + (8*PartX) + (8*PartY) * TempDstStep, 388 TempDstStep, 389 Width, 390 Height, 391 mvx & 3, 392 mvy & 3 393 ); 394 395 } 396 } 397 } 398 } 399 } 400 else 401 { 402 InvalidSAD = 1; 403 } 404 405 /* Calculate SAD from predicted buffer */ 406 if (!InvalidSAD) 407 { 408 OMX_U32 x8x8, y8x8, x4x4, y4x4, Block8x8, Block4x4; 409 OMX_S32 SAD; 410 411 pTempRefBuf = pTempDstBuf; 412 TempRefStep = 16; 413 414 /* SAD for each 4x4 block in scan order */ 415 for (Block8x8 = 0; Block8x8 < 4; Block8x8++) 416 { 417 x8x8 = 8*(Block8x8 & 1); 418 y8x8 = 8*(Block8x8 >> 1); 419 for (Block4x4 = 0; Block4x4 < 4; Block4x4++) 420 { 421 x4x4 = 4*(Block4x4 & 1); 422 y4x4 = 4*(Block4x4 >> 1); 423 424 armVCCOMM_SAD( 425 pSrcCurrBuf + (x8x8 + x4x4) + (y8x8 + y4x4) * SrcCurrStep, 426 SrcCurrStep, 427 pTempRefBuf + (x8x8 + x4x4) + (y8x8 + y4x4) * TempRefStep, 428 TempRefStep, 429 &SAD, 430 4, /* Height */ 431 4); /* Width */ 432 *(pDstBlockSAD + 4 * Block8x8 + Block4x4) = (SAD < 0x7fff) ? (OMX_U16) SAD : ARM_VCM4P10_MAX_MODE_VALUE; 433 } 434 } 435 } 436 else 437 { 438 /* Fill SADs with max values and return*/ 439 for (i = 0; i < 16; i++) 440 { 441 pDstBlockSAD [i] = ARM_VCM4P10_MAX_4x4_SAD; 442 } 443 } 444 return OMX_Sts_NoErr; 445 } 446 447 448 449 /** 450 * Function: armVCM4P10_Mode4x4Decision 451 * 452 * Description: 453 * Intra 4x4 Mode decision by calculating cost for all possible modes and 454 * choosing the best mode 455 * 456 * Remarks: 457 * 458 * Parameters: 459 * [in] pSrcCurrBuf - Pointer to the start of current Macroblock 460 * [in] SrcCurrStep - Step size of the pointer pSrcCurrBuf 461 * [in/out] pSrcDstMBCurr - Pointer to the OMXVCM4P10MBInfo which will be updated for 462 * field pIntra4x4PredMode of the current block. 463 * [in] Block8x8 - Index 8x8 block in which current 4x4 block belongs 464 * [in] Block4x4 - Index of current 4x4 block 465 * [in/out] pPredIntra4x4SrcY - Pointer to current block location in buffer 466 * with reconstructed values. This will be modified by this 467 * function with best mode predicted values 468 * [in] StepPredIntra4x4SrcY - Step size of the pointer pPredIntra4x4SrcY 469 * [in] pIntra4x4PredMode - Array of Intra 4x4 prediction mode for the MB. 470 * Current MB modes starts at [1,1]. 471 * [in] pBestCost - Cost for the Best Intra 4x4 mode 472 * Return Value: 473 * None 474 * 475 */ 476 static OMXVoid armVCM4P10_Mode4x4Decision ( 477 const OMX_U8* pSrcCurrBuf, 478 OMX_S32 SrcCurrStep, 479 OMXVCM4P10MBInfo *pSrcDstMBCurr, 480 OMX_S32 Block8x8, 481 OMX_S32 Block4x4, 482 OMX_U8 *pPredIntra4x4SrcY, 483 OMX_S32 StepPredIntra4x4SrcY, 484 OMX_S32 pIntra4x4PredMode [][9], 485 OMX_S32 *pBestCost 486 ) 487 { 488 OMX_S32 i, j, x, y, BlockX, BlockY, mode; 489 OMX_S32 Cost, BestCost; 490 OMX_U8 *pSrcY; 491 OMX_S32 StepSrcY; 492 OMX_S32 availability = 0; 493 OMX_U8 pPredBlock [4*4]; 494 OMXResult Ret = OMX_Sts_Err; 495 496 /* Get block cordinates from 8x8 block index and 4x4 block index */ 497 BlockX = ((Block8x8 & 1) << 1) + (Block4x4 & 1); 498 BlockY = ((Block8x8 >> 1) << 1) + (Block4x4 >> 1); 499 500 /* Add offset to point to start of current MB in the array pIntra4x4PredMode */ 501 x = BlockX + 1; 502 y = BlockY + 1; 503 504 /* Check for availability of LEFT Block */ 505 if (pIntra4x4PredMode [y][x - 1] != ARM_VCM4P10_INVALID_BLOCK) 506 { 507 availability |= OMX_VC_LEFT; 508 } 509 510 /* Check for availability of UPPER Block */ 511 if (pIntra4x4PredMode [y - 1][x] != ARM_VCM4P10_INVALID_BLOCK) 512 { 513 availability |= OMX_VC_UPPER; 514 } 515 516 /* Check for availability of UPPER LEFT Block */ 517 if (pIntra4x4PredMode [y - 1][x - 1] != ARM_VCM4P10_INVALID_BLOCK) 518 { 519 availability |= OMX_VC_UPPER_LEFT; 520 } 521 522 pSrcY = pPredIntra4x4SrcY + 523 StepPredIntra4x4SrcY * (BlockY << 2) + 524 (BlockX << 2); 525 526 StepSrcY = StepPredIntra4x4SrcY; 527 528 x = BlockX * 4; 529 y = BlockY * 4; 530 531 Cost = BestCost = ARM_VCM4P10_MAX_COST; 532 533 /* Go through each mode for minim cost */ 534 for (mode = 0; mode < 9; mode++) 535 { 536 Ret = omxVCM4P10_PredictIntra_4x4( 537 pSrcY - 1, 538 pSrcY - StepSrcY, 539 pSrcY - StepSrcY - 1, 540 pPredBlock, 541 StepSrcY, 542 4, 543 (OMXVCM4P10Intra4x4PredMode) mode, 544 availability); 545 546 if (Ret == OMX_Sts_NoErr) 547 { 548 armVCCOMM_SAD( 549 pSrcCurrBuf + (y * SrcCurrStep) + x, 550 SrcCurrStep, 551 pPredBlock, 552 4, 553 &Cost, 554 4, 555 4); 556 557 if (Cost < BestCost) 558 { 559 BestCost = Cost; 560 561 pIntra4x4PredMode [BlockY + 1][BlockX + 1] = 562 (OMXVCM4P10Intra4x4PredMode) mode; 563 pSrcDstMBCurr->pIntra4x4PredMode [BlockY * 4 + BlockX] = 564 (OMXVCM4P10Intra4x4PredMode) mode; 565 566 for (j = 0; j < 4; j++) 567 { 568 for (i = 0; i < 4; i++) 569 { 570 pSrcY [StepSrcY * j + i] = pPredBlock [4 * j + i]; 571 } 572 } 573 } 574 } 575 } 576 577 *pBestCost = BestCost; 578 return; 579 } 580 581 /** 582 * Function: armVCM4P10_SetMotionVectorPredictor 583 * 584 * Description: 585 * This function will do the MV Prediction for Inter MBs 586 * 587 * Parameters: 588 * [in] BlockStartX - Start X index in integer pels in current Block 589 * [in] BlockStartY - Start Y index in integer pels in current Block 590 * [in] BlockSizeX - Width of current block 591 * [in] BlockSizeY - Height of current block 592 * [in] RefFrame - Index of the reference frame for prediction 593 * [in] pRefFrArr - Pointer to Ref array storing neighbouring MVs for MV prediction 594 * [in] pMVArr - Pointer to MV array storing neighbouring MVs for MV prediction 595 * [out] pMVPred - Pointer to predicted MVs 596 * Remarks: 597 * 598 * Return Value: 599 * None 600 * 601 */ 602 static OMXVoid armVCM4P10_SetMotionVectorPredictor( 603 OMX_U32 BlockStartX, 604 OMX_U32 BlockStartY, 605 OMX_U32 BlockSizex, 606 OMX_U32 BlockSizey, 607 OMX_S32 RefFrame, 608 OMX_S32 pRefFrArr[][6], 609 OMXVCMotionVector pMVArr[][12], 610 OMXVCMotionVector *pMVPred 611 ) 612 { 613 OMX_S32 RFrameL; /* Left */ 614 OMX_S32 RFrameU; /* Up */ 615 OMX_S32 RFrameUR; /* Up-Right */ 616 617 OMX_S32 BlockX, BlockY, BlockXFr, BlockYFr, MVPredType; 618 OMX_S32 BlockXPlusOff, BlockXPlusOffFr, BlockXMin1Fr, BlockYMin1Fr; 619 620 BlockX = 4 + (BlockStartX >> 2); 621 BlockY = 4 + (BlockStartY >> 2); 622 BlockXPlusOff = BlockX + (BlockSizex >> 2); 623 624 BlockXFr = BlockX >> 1; 625 BlockYFr = BlockY >> 1; 626 BlockXMin1Fr = (BlockX - 1) >> 1; 627 BlockYMin1Fr = (BlockY - 1) >> 1; 628 BlockXPlusOffFr = BlockXPlusOff >> 1; 629 630 MVPredType = ARM_VCM4P10_MVPRED_MEDIAN; 631 632 RFrameL = pRefFrArr [BlockYFr][BlockXMin1Fr]; 633 RFrameU = pRefFrArr [BlockYMin1Fr][BlockXFr]; 634 RFrameUR = pRefFrArr [BlockYMin1Fr][BlockXPlusOffFr]; 635 636 if (RFrameUR == ARM_VCM4P10_INVALID_BLOCK) 637 { 638 RFrameUR = pRefFrArr [BlockYMin1Fr][BlockXMin1Fr]; 639 } 640 641 /* 642 * Prediction if only one of the neighbors uses the reference frame 643 * we are checking 644 */ 645 646 if (RFrameL == RefFrame && RFrameU != RefFrame && RFrameUR != RefFrame) 647 { 648 MVPredType = ARM_VCM4P10_MVPRED_L; 649 } 650 else if(RFrameL != RefFrame && RFrameU == RefFrame && RFrameUR != RefFrame) 651 { 652 MVPredType = ARM_VCM4P10_MVPRED_U; 653 } 654 else if(RFrameL != RefFrame && RFrameU != RefFrame && RFrameUR == RefFrame) 655 { 656 MVPredType = ARM_VCM4P10_MVPRED_UR; 657 } 658 659 /* Directional predictions */ 660 else if(BlockSizex == 8 && BlockSizey == 16) 661 { 662 if(BlockStartX == 0) 663 { 664 if(RFrameL == RefFrame) 665 { 666 MVPredType = ARM_VCM4P10_MVPRED_L; 667 } 668 } 669 else 670 { 671 if (RFrameUR == RefFrame) 672 { 673 MVPredType = ARM_VCM4P10_MVPRED_UR; 674 } 675 } 676 } 677 else if(BlockSizex == 16 && BlockSizey == 8) 678 { 679 if(BlockStartY == 0) 680 { 681 if(RFrameU == RefFrame) 682 { 683 MVPredType = ARM_VCM4P10_MVPRED_U; 684 } 685 } 686 else 687 { 688 if(RFrameL == RefFrame) 689 { 690 MVPredType = ARM_VCM4P10_MVPRED_L; 691 } 692 } 693 } 694 695 switch (MVPredType) 696 { 697 case ARM_VCM4P10_MVPRED_MEDIAN: 698 if (!(pRefFrArr [BlockYMin1Fr][BlockXMin1Fr] == ARM_VCM4P10_INVALID_BLOCK || 699 pRefFrArr [BlockYMin1Fr][BlockXFr] == ARM_VCM4P10_INVALID_BLOCK || 700 pRefFrArr [BlockYMin1Fr][BlockXPlusOffFr] == ARM_VCM4P10_INVALID_BLOCK)) 701 { 702 pMVPred->dx = pMVArr [BlockY][BlockX - 1].dx; 703 pMVPred->dy = pMVArr [BlockY][BlockX - 1].dy; 704 } 705 else 706 { 707 pMVPred->dx = 708 ARM_VCM4P10_MEDIAN(pMVArr [BlockY][BlockX - 1].dx, 709 pMVArr [BlockY - 1][BlockX].dx, 710 pMVArr [BlockY - 1][BlockXPlusOff].dx); 711 pMVPred->dy = 712 ARM_VCM4P10_MEDIAN(pMVArr [BlockY][BlockX - 1].dy, 713 pMVArr [BlockY - 1][BlockX].dy, 714 pMVArr [BlockY - 1][BlockXPlusOff].dy); 715 } 716 break; 717 718 case ARM_VCM4P10_MVPRED_L: 719 pMVPred->dx = pMVArr [BlockY][BlockX - 1].dx; 720 pMVPred->dy = pMVArr [BlockY][BlockX - 1].dy; 721 break; 722 case ARM_VCM4P10_MVPRED_U: 723 pMVPred->dx = pMVArr [BlockY - 1][BlockX].dx; 724 pMVPred->dy = pMVArr [BlockY - 1][BlockX].dy; 725 break; 726 case ARM_VCM4P10_MVPRED_UR: 727 if (pRefFrArr [BlockYMin1Fr][BlockXPlusOffFr] != ARM_VCM4P10_INVALID_BLOCK) 728 { 729 pMVPred->dx = pMVArr [BlockY - 1][BlockXPlusOff].dx; 730 pMVPred->dy = pMVArr [BlockY - 1][BlockXPlusOff].dy; 731 } 732 else 733 { 734 pMVPred->dx = pMVArr [BlockY - 1][BlockX - 1].dx; 735 pMVPred->dy = pMVArr [BlockY - 1][BlockX - 1].dy; 736 } 737 break; 738 default: 739 break; 740 } 741 742 return; 743 } 744 745 /** 746 * Function: armVCM4P10_BlockMotionSearch 747 * 748 * Description: 749 * Gets best MV for the current block 750 * 751 * Parameters: 752 * [in] pSrcCurrBuf - Pointer to the start of luma component of current Macroblock 753 * [in] SrcCurrStep - Step size for the pointer pSrcCurrBuf 754 * [in] pSrcRefY - Pointer to the start of luma component of co-located reference MB 755 * [in] nSrcRefStep - Step size for the pointer pSrcRefY 756 * [in] pRefRect Pointer to the valid reference rectangle; relative to the image origin. 757 * [in] pCurrPointPos Position of the current macroblock in the current plane. 758 * [in] pMESpec - Motion estimation structure 759 * [in] pMBInter - Array, of dimension four, containing pointers to information associated with four 760 * adjacent type INTER MBs (Left, Top, Top-Left, Top-Right). 761 * [in] nLamda - For calculating the cost 762 * [out] pBestCost - Minimum cost for encoding current block 763 * [out] pBestMV - MV corresponding to best cost 764 * [in] BlockStartX - Block start X index in integer pels 765 * [in] BlockStartY - Block start Y index in integer pels 766 * [in] BlockSizeX - Width of current block 767 * [in] BlockSizeY - Height of current block 768 * [in] RefFrame - Index of the reference frame for prediction 769 * [in] pRefFrArr - Pointer to reference frame array storing neighbouring MVs for prediction 770 * [in] pMVArr - Pointer to MV array storing neighbouring MVs for MV prediction 771 * [in] pMVPred - Pointer to MV predicted from neighbour MVs 772 * Remarks: 773 * 774 * Return Value: 775 * OMXResult 776 * 777 */ 778 static OMXResult armVCM4P10_BlockMotionSearch( 779 const OMX_U8* pSrcCurrBuf, 780 OMX_S32 SrcCurrStep, 781 const OMX_U8* pSrcRefY, 782 OMX_S32 nSrcRefStep, 783 const OMXRect *pRefRect, 784 const OMXVCM4P2Coordinate *pCurrPointPos, 785 void* pMESpec, 786 787 OMX_S32 nLamda, 788 OMX_S32* pBestCost, 789 OMXVCMotionVector *pBestMV, 790 791 OMX_U32 BlockStartX, 792 OMX_U32 BlockStartY, 793 OMX_U32 BlockSizeX, 794 OMX_U32 BlockSizeY, 795 OMX_S32 RefFrame, 796 OMX_S32 pRefFrArr [][6], 797 OMXVCMotionVector pMVArr [][12], 798 OMXVCMotionVector *pMVPred 799 ) 800 { 801 802 OMXVCMotionVector MVCalculated, MVCandidate; 803 OMX_S32 Cost; 804 OMXResult RetValue; 805 OMXVCM4P10MEParams *pMEParams; 806 OMXVCM4P2Coordinate CurrBlockPos; 807 808 /* Get Predicted Motion Vectors */ 809 armVCM4P10_SetMotionVectorPredictor ( 810 BlockStartX, 811 BlockStartY, 812 BlockSizeX, 813 BlockSizeY, 814 RefFrame, 815 pRefFrArr, 816 pMVArr, 817 pMVPred); 818 819 /* Initialize candidate MV */ 820 MVCandidate.dx = 0; 821 MVCandidate.dy = 0; 822 823 CurrBlockPos.x = pCurrPointPos->x + BlockStartX; 824 CurrBlockPos.y = pCurrPointPos->y + BlockStartY; 825 826 /* Block Match Integer */ 827 RetValue = omxVCM4P10_BlockMatch_Integer ( 828 pSrcCurrBuf, 829 SrcCurrStep, 830 pSrcRefY, 831 nSrcRefStep, 832 pRefRect, 833 &CurrBlockPos, 834 BlockSizeX, 835 BlockSizeY, 836 nLamda, 837 pMVPred, 838 &MVCandidate, 839 &MVCalculated, 840 &Cost, 841 pMESpec); 842 843 /* updated BestMV*/ 844 /**pBestCost = Cost; 845 pBestMV->dx = MVCalculated.dx; 846 pBestMV->dy = MVCalculated.dy;*/ 847 848 pMEParams = (OMXVCM4P10MEParams *) pMESpec; 849 850 /* Block Match Half pel */ 851 if (pMEParams->halfSearchEnable) 852 { 853 RetValue = omxVCM4P10_BlockMatch_Half( 854 pSrcCurrBuf, 855 SrcCurrStep, 856 pSrcRefY, 857 nSrcRefStep, 858 BlockSizeX, 859 BlockSizeY, 860 nLamda, 861 pMVPred, 862 &MVCalculated, /* input/output*/ 863 &Cost); 864 } 865 866 /* Block Match Quarter pel */ 867 if (pMEParams->quarterSearchEnable) 868 { 869 RetValue = omxVCM4P10_BlockMatch_Quarter( 870 pSrcCurrBuf, 871 SrcCurrStep, 872 pSrcRefY, 873 nSrcRefStep, 874 BlockSizeX, 875 BlockSizeY, 876 nLamda, 877 pMVPred, 878 &MVCalculated, 879 &Cost); 880 } 881 882 /* updated Best Cost and Best MV */ 883 *pBestCost = Cost; 884 pBestMV->dx = MVCalculated.dx; 885 pBestMV->dy = MVCalculated.dy; 886 887 /* 888 * Skip MB cost calculations of 16x16 inter mode 889 */ 890 return RetValue; 891 } 892 893 /** 894 * Function: armVCM4P10_PartitionME 895 * 896 * Description: 897 * Gets best cost for the current partition 898 * 899 * Parameters: 900 * [in] pSrcCurrBuf - Pointer to the start of luma component of current Macroblock 901 * [in] SrcCurrStep - Step size for the pointer pSrcCurrBuf 902 * [in] pSrcRefBufList - Pointer to List of ref buffer of co-located reference MB 903 * [in] nSrcRefStep - Step size for the pointer pSrcRefY 904 * [in] pRefRect Pointer to the valid reference rectangle; relative to the image origin. 905 * [in] pCurrPointPos Position of the current macroblock in the current plane. 906 * [in] pMESpec - Motion estimation structure 907 * [in] PartWidth - Width of current partition 908 * [in] PartHeight - Height of current partition 909 * [in] BlockWidth - Width of current block 910 * [in] BlockHeight - Height of current block 911 * [in] PartStartX - Partition start X index in integer pels 912 * [in] PartStartY - Partition start Y index in integer pels 913 * [in] pMVArr - Pointer to MV array storing neighbouring MVs for MV prediction 914 * [in] pRefFrArr - Pointer to reference frame array storing neighbouring MVs for prediction 915 * [in] Lambda - For calculating the cost 916 * [out] pCost - Pointer to cost for Inter MB 917 * 918 * Return Value: 919 * OMXResult 920 * 921 */ 922 static OMXResult armVCM4P10_PartitionME ( 923 const OMX_U8* pSrcCurrBuf, 924 OMX_S32 SrcCurrStep, 925 const OMX_U8 *pSrcRefBufList[ARM_VCM4P10_MAX_FRAMES], 926 OMX_S32 SrcRefStep, 927 const OMXRect *pRefRect, 928 const OMXVCM4P2Coordinate *pCurrPointPos, 929 void* pMESpec, 930 931 OMX_S32 PartWidth, 932 OMX_S32 PartHeight, 933 OMX_S32 BlockWidth, 934 OMX_S32 BlockHeight, 935 OMX_S32 PartStartX, 936 OMX_S32 PartStartY, 937 938 OMXVCMotionVector pMVArr [][12], 939 OMX_S32 pRefFrArr [][6], 940 OMXVCMotionVector pMVPredArr [][4], 941 942 OMX_S32 Lambda, 943 OMX_S32 *pCost 944 ) 945 { 946 OMX_U32 x, y, i, j, ref, OffX, OffY, OffSrc, OffRef; 947 OMX_S32 BlockCost, PartitionCost, BestCost; 948 OMX_S32 BestRefFrame=0; 949 OMXVCMotionVector BestMV [4][4]; 950 OMXVCMotionVector BestMVPred [4][4]; 951 OMXVCMotionVector MVPred; 952 OMXVCMotionVector DstMV; 953 954 BestCost = ARM_VCM4P10_MAX_COST; 955 956 for (ref = 0; ref < ARM_VCM4P10_MAX_FRAMES; ref++) 957 { 958 if (pSrcRefBufList [ref] == NULL) 959 { 960 /* No reference frame, continue */ 961 continue; 962 } 963 964 PartitionCost = 0; 965 966 for (y = 0; y < PartHeight; y += BlockHeight) 967 { 968 for (x = 0; x < PartWidth; x += BlockWidth) 969 { 970 OffSrc = SrcCurrStep * (PartStartY + y) + PartStartX + x; 971 OffRef = SrcRefStep * (PartStartY + y) + PartStartX + x; 972 armVCM4P10_BlockMotionSearch ( 973 pSrcCurrBuf + OffSrc, 974 SrcCurrStep, 975 pSrcRefBufList [ref] + OffRef, 976 SrcRefStep, 977 pRefRect, 978 pCurrPointPos, 979 pMESpec, 980 981 Lambda, 982 &BlockCost, 983 &DstMV, 984 985 x + PartStartX, 986 y + PartStartY, 987 BlockWidth, 988 BlockHeight, 989 ref, 990 pRefFrArr, 991 pMVArr, 992 &MVPred); 993 994 PartitionCost += BlockCost; 995 996 OffX = (PartStartX + x) >> 2; 997 OffY = (PartStartY + y) >> 2; 998 999 for (j = 0; j < (BlockHeight >> 2); j++) 1000 { 1001 for (i = 0; i < (BlockWidth >> 2); i++) 1002 { 1003 pMVArr [4 + OffY + j][4 + OffX + i].dx = DstMV.dx; 1004 pMVArr [4 + OffY + j][4 + OffX + i].dy = DstMV.dy; 1005 pMVPredArr [OffY + j][OffX + i].dx = MVPred.dx; 1006 pMVPredArr [OffY + j][OffX + i].dy = MVPred.dy; 1007 } 1008 } 1009 1010 pRefFrArr [2 + (OffY >> 1)][2 + (OffX >> 1)] = ref; 1011 for (j = 0; j < (BlockHeight >> 3); j++) 1012 { 1013 for (i = 0; i < (BlockWidth >> 3); i++) 1014 { 1015 pRefFrArr [2 + (OffY >> 1) + j][2 + (OffX >> 1) + i] = ref; 1016 } 1017 } 1018 1019 } 1020 } 1021 1022 /* 1023 * If PartitionCost is less for this reference frame, motion vectors needs to be backedup 1024 */ 1025 if (PartitionCost <= BestCost) 1026 { 1027 BestCost = PartitionCost; 1028 BestRefFrame = ref; 1029 1030 for (y = 0; y < (PartHeight/BlockHeight); y++) 1031 { 1032 for (x = 0; x < (PartWidth/BlockWidth); x++) 1033 { 1034 OffX = (PartStartX + x * BlockWidth) >> 2; 1035 OffY = (PartStartY + y * BlockHeight) >> 2; 1036 1037 BestMV[y][x].dx = pMVArr [4 + OffY][4 + OffX].dx; 1038 BestMV[y][x].dy = pMVArr [4 + OffY][4 + OffX].dy; 1039 BestMVPred[y][x].dx = pMVPredArr [OffY][OffX].dx; 1040 BestMVPred[y][x].dy = pMVPredArr [OffY][OffX].dy; 1041 } 1042 } 1043 } 1044 1045 } 1046 1047 /* 1048 * Copy back best reference frame, motion vectors and cost. 1049 */ 1050 for (y = 0; y < (PartHeight/BlockHeight); y++) 1051 { 1052 for (x = 0; x < (PartWidth/BlockWidth); x++) 1053 { 1054 OffX = (PartStartX + x * BlockWidth) >> 2; 1055 OffY = (PartStartY + y * BlockHeight) >> 2; 1056 1057 for (j = 0; j < (BlockHeight >> 2); j++) 1058 { 1059 for (i = 0; i < (BlockWidth >> 2); i++) 1060 { 1061 pMVArr [4 + OffY + j][4 + OffX + i].dx = BestMV[y][x].dx; 1062 pMVArr [4 + OffY + j][4 + OffX + i].dy = BestMV[y][x].dy; 1063 pMVPredArr [OffY + j][OffX + i].dx = BestMVPred[y][x].dx; 1064 pMVPredArr [OffY + j][OffX + i].dy = BestMVPred[y][x].dy; 1065 } 1066 } 1067 1068 for (j = 0; j < (BlockHeight >> 3); j++) 1069 { 1070 for (i = 0; i < (BlockWidth >> 3); i++) 1071 { 1072 pRefFrArr [2 + (OffY >> 1) + j][2 + (OffX >> 1) + i] = BestRefFrame; 1073 } 1074 } 1075 } 1076 } 1077 1078 *pCost = BestCost; 1079 return OMX_Sts_NoErr; 1080 1081 } 1082 1083 /** 1084 * Function: armVCM4P10_Intra16x16Estimation 1085 * 1086 * Description: 1087 * Performs MB-level motion estimation for INTER MB type and selects best motion estimation strategy from 1088 * the set of modes supported in baseline profile ISO/IEC 14496-10. 1089 * 1090 * Remarks: 1091 * 1092 * Parameters: 1093 * [in] pSrcCurrBuf - Pointer to the start of luma component of current Macroblock 1094 * [in] SrcCurrStep - Step size for the pointer pSrcCurrBuf 1095 * [in] pSrcRecBuf - Pointer to the start of luma component of co-located reconstructed MB 1096 * [in] SrcRecStep - Step size for the pointer pSrcRecBuf 1097 * [in] nMBPosX - Position of MB in the frame w.r.t X axis 1098 * [in] nMBPosY - Position of MB in the frame w.r.t Y axis 1099 * [in] pMBInter - Array, of dimension four, containing pointers to information associated with four 1100 * adjacent type INTER MBs (Left, Top, Top-Left, Top-Right). 1101 * [in] pMBIntra - Array, of dimension four, containing pointers to information associated with four 1102 * adjacent type INTRA MBs (Left, Top, Top-Left, Top-Right). 1103 * [in/out] pSrcDstMBCurr - Pointer to information structure for the current MB. Following member should be set 1104 * before calling this function 1105 * [in] Lambda - For calculating the cost 1106 * [out] pCost - Pointer to cost for Intra16x16 1107 * Return Value: 1108 * OMX_Sts_NoErr - No Error 1109 * OMX_Sts_BadArgErr - Bad arguments: 1110 * 1111 */ 1112 1113 static OMXResult armVCM4P10_Intra16x16Estimation( 1114 const OMX_U8* pSrcCurrBuf, 1115 OMX_S32 SrcCurrStep, 1116 const OMX_U8* pSrcRecBuf, 1117 OMX_S32 SrcRecStep, 1118 const OMXVCM4P2Coordinate *pCurrPointPos, 1119 const OMXVCM4P10MBInfoPtr *pMBInter, 1120 const OMXVCM4P10MBInfoPtr *pMBIntra, 1121 OMXVCM4P10MBInfo *pSrcDstMBCurr, 1122 OMX_U32 *pCost) 1123 { 1124 OMX_U8 PredBuf [16*16 + 16]; 1125 OMX_U8 *pPred; 1126 OMX_S32 mode; 1127 OMX_S32 Cost; 1128 OMX_S32 availability = 0; 1129 OMXResult Ret; 1130 OMXVCM4P10Intra16x16PredMode IntraMode16x16 [4] = 1131 {OMX_VC_16X16_VERT, OMX_VC_16X16_HOR, 1132 OMX_VC_16X16_DC, OMX_VC_16X16_PLANE}; 1133 OMX_U32 MBPosX = pCurrPointPos->x >> 4; 1134 OMX_U32 MBPosY = pCurrPointPos->y >> 4; 1135 1136 pPred = armAlignTo16Bytes(PredBuf); 1137 1138 /* Check for availability of LEFT MB */ 1139 if ((MBPosX != 0) && (pMBIntra [0] != 0 || pMBInter [0] != 0)) 1140 { 1141 availability |= OMX_VC_LEFT; 1142 } 1143 1144 /* Check for availability of UP MB */ 1145 if ((MBPosY != 0) && (pMBIntra [1] != 0 || pMBInter [1] != 0)) 1146 { 1147 availability |= OMX_VC_UPPER; 1148 } 1149 1150 /* Check for availability of UP-LEFT MB */ 1151 if ((MBPosX > 0) && (MBPosY > 0) && 1152 (pMBIntra [2] != 0 || pMBInter [2] != 0)) 1153 { 1154 availability |= OMX_VC_UPPER_LEFT; 1155 } 1156 1157 *pCost = ARM_VCM4P10_MAX_COST; 1158 for (mode = 0; mode < 4; mode++) 1159 { 1160 Ret = omxVCM4P10_PredictIntra_16x16( 1161 pSrcRecBuf - 1, 1162 pSrcRecBuf - SrcRecStep, 1163 pSrcRecBuf - SrcRecStep - 1, 1164 pPred, 1165 SrcRecStep, 1166 16, 1167 IntraMode16x16 [mode], 1168 availability); 1169 if (Ret == OMX_Sts_NoErr) 1170 { 1171 armVCCOMM_SAD( 1172 pSrcCurrBuf, 1173 SrcCurrStep, 1174 pPred, 1175 16, 1176 &Cost, 1177 16, 1178 16); 1179 if (Cost < *pCost) 1180 { 1181 *pCost = Cost; 1182 pSrcDstMBCurr->Intra16x16PredMode = IntraMode16x16 [mode]; 1183 } 1184 1185 } 1186 1187 } 1188 1189 return OMX_Sts_NoErr; 1190 } 1191 1192 /** 1193 * Function: armVCM4P10_Intra4x4Estimation 1194 * 1195 * Description: 1196 * Performs MB-level motion estimation for Intra 4x4 MB type and selects 1197 * the best set of modes supported in baseline profile. 1198 * 1199 * Parameters: 1200 * [in] pSrcCurrBuf - Pointer to the start of luma component of current Macroblock 1201 * [in] SrcCurrStep - Step size for the pointer pSrcCurrBuf 1202 * [in] pSrcRecBuf - Pointer to the start of luma component of co-located reconstructed MB 1203 * [in] SrcRecStep - Step size for the pointer pSrcRecBuf 1204 * [in] nMBPosX - Position of MB in the frame w.r.t X axis 1205 * [in] nMBPosY - Position of MB in the frame w.r.t Y axis 1206 * [in] pMBIntra - Array, of dimension four, containing pointers to information associated with four 1207 * adjacent type INTRA MBs (Left, Top, Top-Left, Top-Right). 1208 * [in/out] pSrcDstMBCurr - Pointer to information structure for the current MB. Following member should be set 1209 * before calling this function 1210 * [in] Lambda - For calculating the cost 1211 * [out] pCost - Pointer to cost for Intra4x4 1212 * Return Value: 1213 * OMX_Sts_NoErr - No Error 1214 * OMX_Sts_BadArgErr - Bad arguments: 1215 * 1216 */ 1217 1218 static OMXResult armVCM4P10_Intra4x4Estimation( 1219 const OMX_U8* pSrcCurrBuf, 1220 OMX_S32 SrcCurrStep, 1221 const OMX_U8* pSrcRecBuf, 1222 OMX_S32 SrcRecStep, 1223 const OMXVCM4P10MBInfoPtr *pMBIntra, 1224 OMXVCM4P10MBInfo *pSrcDstMBCurr, 1225 OMX_U32 *pCost) 1226 { 1227 OMX_S32 x, y, Block4x4, Block8x8; 1228 OMX_S32 Cost; 1229 1230 /* 1231 * PredIntra4x4Mode will store prediction modes of 4x4 blocks. 1232 * Modes for current MB starts at index [1][1]. 1233 * Modes of nighbouring MB's will be as shown below 1234 * A value of ARM_VCM4P10_INVALID_BLOCK for any block in this array means 1235 * that block is not available for prediction. 1236 * 1237 * c3 b0 b1 b2 b3 d0 d1 d2 d3 1238 * a0 xx xx xx xx - - - - 1239 * a1 xx xx xx xx - - - - 1240 * a2 xx xx xx xx - - - - 1241 * a3 xx xx xx xx - - - - 1242 * 1243 */ 1244 OMX_S32 PredIntra4x4Mode [5][9]; 1245 1246 /* 1247 * pSrcY stores re-construsted source array of size 3MB X 2MB as below 1248 * 1249 * MB11 MB12 MB13 1250 * MB21 MB22 MB23 1251 * 1252 * This array will be used for local reconstruction of 4x4 blocks 1253 * with best prediction mode within an MB 1254 */ 1255 OMX_U8 pSrcY [(16*3)*(16*2)]; 1256 OMX_S32 StepSrcY; 1257 1258 /* init */ 1259 *pCost = 0; 1260 1261 for (y = 0; y < 5; y++) 1262 { 1263 for (x = 0; x < 9; x++) 1264 { 1265 /* 1266 * Initialize with value of ARM_VCM4P10_INVALID_BLOCK, to mean this 1267 * 4x4 block is not available 1268 */ 1269 PredIntra4x4Mode [y][x] = ARM_VCM4P10_INVALID_BLOCK; 1270 } 1271 } 1272 1273 /* Replace ARM_VCM4P10_INVALID_BLOCK value with available MBs values*/ 1274 for (x = 0; x < 4; x++) 1275 { 1276 /* Store values of b0, b1, b2, b3 */ 1277 if (pMBIntra[1] != NULL) 1278 { 1279 PredIntra4x4Mode [0][x + 1] = 1280 pMBIntra[1]->pIntra4x4PredMode[3*4 + x]; 1281 } 1282 1283 /* Store values of d0, d1, d2, d3 */ 1284 if (pMBIntra[3] != NULL) 1285 { 1286 PredIntra4x4Mode [0][x + 5] = 1287 pMBIntra[3]->pIntra4x4PredMode[3*4 + x]; 1288 } 1289 } 1290 1291 /* Store values of c3 */ 1292 if (pMBIntra[2] != NULL) 1293 { 1294 PredIntra4x4Mode [0][0] = pMBIntra[2]->pIntra4x4PredMode[15]; 1295 } 1296 1297 for (y = 0; y < 4; y++) 1298 { 1299 /* Store values of a0, a1, a2, a3 */ 1300 if (pMBIntra[0] != NULL) 1301 { 1302 PredIntra4x4Mode [y + 1][0] = 1303 pMBIntra[0]->pIntra4x4PredMode[y*4 + 3]; 1304 } 1305 } 1306 1307 /* 1308 * Update neighbouring Pred mode array which will be used for 1309 * prediction of Intra4x4 modes. 1310 */ 1311 1312 StepSrcY = 16 * 3; 1313 for (y = 0; y < (16 * 2); y++) 1314 { 1315 for (x = 0; x < (16 * 3); x++) 1316 { 1317 pSrcY [StepSrcY * y + x] = 1318 pSrcRecBuf [SrcRecStep * (y - 16) + x - 16]; 1319 } 1320 } 1321 1322 /* for each 8x8 block */ 1323 for (Block8x8 = 0; Block8x8 < 4; Block8x8++) 1324 { 1325 /* for each 4x4 block inside 8x8 block */ 1326 for (Block4x4 = 0; Block4x4 < 4; Block4x4++) 1327 { 1328 armVCM4P10_Mode4x4Decision ( 1329 pSrcCurrBuf, 1330 SrcCurrStep, 1331 pSrcDstMBCurr, 1332 Block8x8, 1333 Block4x4, 1334 pSrcY + 16 * StepSrcY + 16, 1335 StepSrcY, 1336 PredIntra4x4Mode, 1337 &Cost); 1338 1339 *pCost += Cost; 1340 } 1341 } 1342 return OMX_Sts_NoErr; 1343 } 1344 1345 /** 1346 * Function: armVCM4P10_InterMEMB 1347 * 1348 * Description: 1349 * Performs MB-level motion estimation for INTER MB type and selects best motion estimation strategy from 1350 * the set of modes supported in baseline profile ISO/IEC 14496-10. 1351 * 1352 * Remarks: 1353 * 1354 * Parameters: 1355 * [in] pSrcCurrBuf - Pointer to the start of luma component of current Macroblock 1356 * [in] SrcCurrStep - Step size for the pointer pSrcCurrBuf 1357 * [in] pSrcRefBufList - Pointer to the start of luma component of co-located reference MB 1358 * [in] SrcRefStep - Step size for the pointer pSrcRefY 1359 * [in] pRefRect Pointer to the valid reference rectangle; relative to the image origin. 1360 * [in] pCurrPointPos Position of the current macroblock in the current plane. 1361 * [in] pMESpec - Motion estimation structure 1362 * [in] pMBInter - Array, of dimension four, containing pointers to information associated with four 1363 * adjacent type INTER MBs (Left, Top, Top-Left, Top-Right). 1364 * [in/out] pSrcDstMBCurr - Pointer to information structure for the current MB. Following member should be set 1365 * before calling this function 1366 * [in] Lambda - For calculating the cost 1367 * [out] pDstCost - Pointer to cost for Inter MB 1368 * Return Value: 1369 * OMX_Sts_NoErr - No Error 1370 * OMX_Sts_BadArgErr - Bad arguments: 1371 * 1372 */ 1373 1374 static OMXResult armVCM4P10_InterMEMB( 1375 const OMX_U8 *pSrcCurrBuf, 1376 OMX_S32 SrcCurrStep, 1377 const OMX_U8 *pSrcRefBufList[ARM_VCM4P10_MAX_FRAMES], 1378 OMX_S32 SrcRefStep, 1379 const OMXRect *pRefRect, 1380 const OMXVCM4P2Coordinate *pCurrPointPos, 1381 OMX_U32 Lambda, 1382 void *pMESpec, 1383 const OMXVCM4P10MBInfoPtr *pMBInter, 1384 OMXVCM4P10MBInfoPtr pSrcDstMBCurr, 1385 OMX_U32 *pDstCost) 1386 { 1387 OMX_S32 i, j, x, y, mode; 1388 OMX_U32 Block8x8, XPerMB, YPerMB, Block2x, Block2y; 1389 OMX_S32 PartStartX = 0, PartStartY = 0; 1390 OMX_S32 PartWidth = 8, PartHeight = 8, BlockWidth = 4, BlockHeight = 4; 1391 const OMX_U32 BlkSz [4][2] = {{4,4}, {4,8}, {8,4}}; 1392 const OMX_U32 PartSz [4][2] = {{8,8}, {8,16}, {16,8}, {16,16}}; 1393 const OMXVCM4P10SubMacroblockType 1394 ModeSubMBType4x4 [] = {OMX_VC_SUB_P_4x4, OMX_VC_SUB_P_4x8, 1395 OMX_VC_SUB_P_8x4, OMX_VC_SUB_P_8x8}; 1396 const OMXVCM4P10MacroblockType 1397 ModeMBType [] = {OMX_VC_P_8x8, OMX_VC_P_8x16, OMX_VC_P_16x8, OMX_VC_P_16x16}; 1398 1399 OMXVCM4P10MEParams *pMBOptions; 1400 /* 1401 * RefFrArr and MVArr will be used for temporary storage of Reference frame index and MVs 1402 * It will store RefIndex and MVs of 6 MBs as shown below 1403 * 1404 * |------|------|------| 1405 * |Tp-Lt |Top |Tp-R | 1406 * | MB | MB | MB | 1407 * |------|------|------| 1408 * |Left | Curr | | 1409 * | MB | MB | | 1410 * |------|------|------| 1411 */ 1412 OMX_S32 RefFrArr [4][6]; 1413 OMXVCMotionVector MVArr [8][12]; 1414 OMXVCMotionVector MVPredArr [4][4]; 1415 1416 /* 1417 * IndexToLoc will translate pMBInter index into spacial arrangement of MBs 1418 */ 1419 OMX_S32 IndexToLoc [] = {2,1,3,0}; 1420 OMX_U32 part, MaxPart; 1421 OMX_S32 Cost, MotionCost8x8 [4], MBCost, BestCost; 1422 1423 /* 1424 * Update neighbouring MV array and Ref frame array which will be used for 1425 * prediction of MVs and Ref frames. 1426 */ 1427 1428 /* Set cost to a high value */ 1429 Cost = BestCost = ARM_VCM4P10_MAX_COST; 1430 1431 for (y = 0; y < 8; y++) 1432 { 1433 for (x = 0; x < 12; x++) 1434 { 1435 i = 3 * (y >> 2) + (x >> 2); 1436 if ((y < 4 || x < 4) && (pMBInter[IndexToLoc[i]] != NULL)) 1437 { 1438 MVArr [y][x].dx = 1439 pMBInter[IndexToLoc[i]]->pMV0[y % 4][x % 4].dx; 1440 MVArr [y][x].dy = 1441 pMBInter[IndexToLoc[i]]->pMV0[y % 4][x % 4].dy; 1442 } 1443 else 1444 { 1445 MVArr [y][x].dx = 0; 1446 MVArr [y][x].dy = 0; 1447 } 1448 } 1449 } 1450 1451 for (y = 0; y < 4; y++) 1452 { 1453 for (x = 0; x < 6; x++) 1454 { 1455 i = 3 * (y >> 1) + (x >> 1); 1456 if ((y < 2 || x < 2) && (pMBInter[IndexToLoc[i]] != NULL)) 1457 { 1458 RefFrArr [y][x] = 1459 pMBInter[IndexToLoc[i]]->pRefL0Idx [(y % 2) * 2 + (x % 2)]; 1460 } 1461 else 1462 { 1463 RefFrArr [y][x] = ARM_VCM4P10_INVALID_BLOCK; 1464 } 1465 } 1466 } 1467 1468 for (y = 0; y < 4; y++) 1469 { 1470 for (x = 0; x < 4; x++) 1471 { 1472 MVPredArr [y][x].dx = 0; 1473 MVPredArr [y][x].dy = 0; 1474 } 1475 } 1476 /* 1477 * Motion Estimation for 8x8 MB Partition 1478 */ 1479 1480 for (i = 0; i < 4; i++) 1481 { 1482 MotionCost8x8 [i] = 0; 1483 } 1484 1485 pMBOptions = (OMXVCM4P10MEParams *) pMESpec; 1486 1487 if (pMBOptions->blockSplitEnable8x8 == 1 && 1488 pMBOptions->blockSplitEnable4x4 == 1) 1489 { 1490 pSrcDstMBCurr->mbType = OMX_VC_P_8x8; 1491 1492 PartWidth = PartSz [0][0]; 1493 PartHeight = PartSz [0][1]; 1494 1495 /* For each 8x8 partitions */ 1496 for (Block8x8 = 0; Block8x8 < 4; Block8x8++) 1497 { 1498 PartStartX = (Block8x8 % 2) << 3; 1499 PartStartY = (Block8x8 / 2) << 3; 1500 1501 Block2x = (Block8x8 & 1) << 1; 1502 Block2y = (Block8x8 >> 1) << 1; 1503 1504 BestCost = ARM_VCM4P10_MAX_COST; 1505 for (mode = 0; mode < 3; mode++) 1506 { 1507 BlockWidth = BlkSz [mode][0]; 1508 BlockHeight = BlkSz [mode][1]; 1509 1510 armVCM4P10_PartitionME ( 1511 pSrcCurrBuf, 1512 SrcCurrStep, 1513 pSrcRefBufList, 1514 SrcRefStep, 1515 pRefRect, 1516 pCurrPointPos, 1517 pMESpec, 1518 1519 PartWidth, 1520 PartHeight, 1521 BlockWidth, 1522 BlockHeight, 1523 PartStartX, 1524 PartStartY, 1525 1526 MVArr, 1527 RefFrArr, 1528 MVPredArr, 1529 1530 Lambda, 1531 &Cost); 1532 1533 if (Cost <= BestCost) 1534 { 1535 /* Update cost */ 1536 BestCost = Cost; 1537 1538 /* Update MBCurr struct */ 1539 pSrcDstMBCurr->subMBType [Block8x8] = ModeSubMBType4x4 [mode]; 1540 1541 pSrcDstMBCurr->pRefL0Idx [Block8x8] = RefFrArr [2 + (PartStartY >> 3)][2 + (PartStartX >> 3)]; 1542 1543 /* Update pMV0 and pMVPred of MBCurr struct */ 1544 for (j = 0; j < 2; j++) 1545 { 1546 for (i = 0; i < 2; i++) 1547 { 1548 pSrcDstMBCurr->pMV0 [Block2y + j][Block2x + i].dx = 1549 MVArr [4 + Block2y + j][4 + Block2x + i].dx; 1550 pSrcDstMBCurr->pMV0 [Block2y + j][Block2x + i].dy = 1551 MVArr [4 + Block2y + j][4 + Block2x + i].dy; 1552 1553 pSrcDstMBCurr->pMVPred [Block2y + j][Block2x + i].dx = 1554 MVPredArr [Block2y + j][Block2x + i].dx; 1555 pSrcDstMBCurr->pMVPred [Block2y + j][Block2x + i].dy = 1556 MVPredArr [Block2y + j][Block2x + i].dy; 1557 } 1558 } 1559 } 1560 } 1561 1562 /* Update cost */ 1563 MotionCost8x8 [Block8x8] = BestCost; 1564 } 1565 1566 /* Cost for mbType OMX_VC_P_8x8 */ 1567 BestCost = 0; 1568 for (i = 0; i < 4; i++) 1569 { 1570 BestCost += MotionCost8x8 [i]; 1571 } 1572 } 1573 else 1574 { 1575 /* Set sub MB type to 8x8 */ 1576 for (i = 0; i < 4; i++) 1577 { 1578 pSrcDstMBCurr->subMBType [i] = OMX_VC_SUB_P_8x8; 1579 } 1580 } 1581 1582 /* 1583 * Motion Estimation for 8x8, 8x16, 16x8 and 16x16 MB Partition 1584 * If pMBOptions->b8x8BlockSplitEnable is 0, do only 16x16 ME (mode 3) 1585 */ 1586 for (mode = (pMBOptions->blockSplitEnable8x8 == 1 ? 0 : 3); mode < 4; mode++) 1587 { 1588 BlockWidth = PartWidth = PartSz [mode][0]; 1589 BlockHeight = PartHeight = PartSz [mode][1]; 1590 1591 XPerMB = 16 / PartWidth; 1592 YPerMB = 16 / PartHeight; 1593 MaxPart = XPerMB * YPerMB; 1594 1595 MBCost = 0; 1596 1597 /* part size 4, 2, 2 and 1 corresponding to 8x8, 8x16, 16x8 and 16x16 MB */ 1598 for (part = 0; part < MaxPart; part++) 1599 { 1600 PartStartX = (part % XPerMB) * PartWidth; 1601 PartStartY = (part / XPerMB) * PartHeight; 1602 1603 armVCM4P10_PartitionME ( 1604 pSrcCurrBuf, 1605 SrcCurrStep, 1606 pSrcRefBufList, 1607 SrcRefStep, 1608 pRefRect, 1609 pCurrPointPos, 1610 pMESpec, 1611 1612 PartWidth, 1613 PartHeight, 1614 BlockWidth, 1615 BlockHeight, 1616 PartStartX, 1617 PartStartY, 1618 1619 MVArr, 1620 RefFrArr, 1621 MVPredArr, 1622 1623 Lambda, 1624 &Cost); 1625 1626 MBCost += Cost; 1627 } 1628 1629 if (MBCost <= BestCost) 1630 { 1631 /* Update cost */ 1632 BestCost = MBCost; 1633 1634 /* Update mbType of MBCurr struct */ 1635 pSrcDstMBCurr->mbType = ModeMBType [mode]; 1636 1637 /* Update pMV0 and pMVPred of MBCurr struct */ 1638 for (j = 0; j < 4; j++) 1639 { 1640 for (i = 0; i < 4; i++) 1641 { 1642 pSrcDstMBCurr->pMV0 [j][i].dx = MVArr [4+j][4+i].dx; 1643 pSrcDstMBCurr->pMV0 [j][i].dy = MVArr [4+j][4+i].dy; 1644 pSrcDstMBCurr->pMVPred [j][i].dx = MVPredArr [j][i].dx; 1645 pSrcDstMBCurr->pMVPred [j][i].dy = MVPredArr [j][i].dy; 1646 } 1647 } 1648 for (j = 0; j < 2; j++) 1649 { 1650 for (i = 0; i < 2; i++) 1651 { 1652 pSrcDstMBCurr->pRefL0Idx [j*2+i] = RefFrArr [2+j][2+i]; 1653 } 1654 } 1655 } 1656 1657 } 1658 1659 /* Update Best Cost */ 1660 *pDstCost = BestCost; 1661 1662 return OMX_Sts_NoErr; 1663 } 1664 1665 /** 1666 * Function: omxVCM4P10_MotionEstimationMB (6.3.5.3.1) 1667 * 1668 * Description: 1669 * Performs MB-level motion estimation and selects best motion estimation 1670 * strategy from the set of modes supported in baseline profile [ISO14496-10]. 1671 * 1672 * Input Arguments: 1673 * 1674 * pSrcCurrBuf - Pointer to the current position in original picture plane; 1675 * 16-byte alignment required 1676 * pSrcRefBufList - Pointer to an array with 16 entries. Each entry points 1677 * to the top-left corner of the co-located MB in a reference 1678 * picture. The array is filled from low-to-high with valid 1679 * reference frame pointers; the unused high entries should be set 1680 * to NULL. Ordering of the reference frames should follow 1681 * [ISO14496-10] subclause 8.2.4 Decoding Process for Reference 1682 * Picture Lists. The entries must be 16-byte aligned. 1683 * pSrcRecBuf - Pointer to the top-left corner of the co-located MB in the 1684 * reconstructed picture; must be 16-byte aligned. 1685 * SrcCurrStep - Width of the original picture plane in terms of full 1686 * pixels; must be a multiple of 16. 1687 * SrcRefStep - Width of the reference picture plane in terms of full 1688 * pixels; must be a multiple of 16. 1689 * SrcRecStep - Width of the reconstructed picture plane in terms of full 1690 * pixels; must be a multiple of 16. 1691 * pRefRect - Pointer to the valid reference rectangle; relative to the 1692 * image origin. 1693 * pCurrPointPos - Position of the current macroblock in the current plane. 1694 * Lambda - Lagrange factor for computing the cost function 1695 * pMESpec - Pointer to the motion estimation specification structure; must 1696 * have been allocated and initialized prior to calling this 1697 * function. 1698 * pMBInter - Array, of dimension four, containing pointers to information 1699 * associated with four adjacent type INTER MBs (Left, Top, 1700 * Top-Left, Top-Right). Any pointer in the array may be set equal 1701 * to NULL if the corresponding MB doesn t exist or is not of type 1702 * INTER. pMBInter[0] - Pointer to left MB information pMBInter[1] 1703 * - Pointer to top MB information pMBInter[2] - Pointer to 1704 * top-left MB information pMBInter[3] - Pointer to top-right MB 1705 * information 1706 * pMBIntra - Array, of dimension four, containing pointers to information 1707 * associated with four adjacent type INTRA MBs (Left, Top, 1708 * Top-Left, Top-Right). Any pointer in the array may be set equal 1709 * to NULL if the corresponding MB doesn t exist or is not of type 1710 * INTRA. pMBIntra[0] - Pointer to left MB information pMBIntra[1] 1711 * - Pointer to top MB information pMBIntra[2] - Pointer to 1712 * top-left MB information pMBIntra[3] - Pointer to top-right MB 1713 * information 1714 * pSrcDstMBCurr - Pointer to information structure for the current MB. 1715 * The following entries should be set prior to calling the 1716 * function: sliceID - the number of the slice the to which the 1717 * current MB belongs. 1718 * 1719 * Output Arguments: 1720 * 1721 * pDstCost - Pointer to the minimum motion cost for the current MB. 1722 * pDstBlockSAD - Pointer to the array of SADs for each of the sixteen luma 1723 * 4x4 blocks in each MB. The block SADs are in scan order for 1724 * each MB. For implementations that cannot compute the SAD values 1725 * individually, the maximum possible value (0xffff) is returned 1726 * for each of the 16 block SAD entries. 1727 * pSrcDstMBCurr - Pointer to updated information structure for the current 1728 * MB after MB-level motion estimation has been completed. The 1729 * following fields are updated by the ME function. The following 1730 * parameter set quantifies the MB-level ME search results: MbType 1731 * subMBType[4] pMV0[4][4] pMVPred[4][4] pRefL0Idx[4] 1732 * Intra16x16PredMode pIntra4x4PredMode[4][4] 1733 * 1734 * Return Value: 1735 * OMX_Sts_NoErr, if the function runs without error. 1736 * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs: 1737 * - One of more of the following pointers is NULL: pSrcCurrBuf, 1738 * pSrcRefBufList, pSrcRecBuf, pRefRect, pCurrPointPos, pMESpec, 1739 * pMBInter, pMBIntra,pSrcDstMBCurr, pDstCost, pSrcRefBufList[0] 1740 * - SrcRefStep, SrcRecStep are not multiples of 16 1741 * - iBlockWidth or iBlockHeight are values other than 4, 8, or 16. 1742 * - Any alignment restrictions are violated 1743 * 1744 */ 1745 1746 OMXResult omxVCM4P10_MotionEstimationMB( 1747 const OMX_U8 *pSrcCurrBuf, 1748 OMX_S32 SrcCurrStep, 1749 const OMX_U8 *pSrcRefBufList[ARM_VCM4P10_MAX_FRAMES], 1750 OMX_S32 SrcRefStep, 1751 const OMX_U8 *pSrcRecBuf, 1752 OMX_S32 SrcRecStep, 1753 const OMXRect *pRefRect, 1754 const OMXVCM4P2Coordinate *pCurrPointPos, 1755 OMX_U32 Lambda, 1756 void *pMESpec, 1757 const OMXVCM4P10MBInfoPtr *pMBInter, 1758 const OMXVCM4P10MBInfoPtr *pMBIntra, 1759 OMXVCM4P10MBInfo *pSrcDstMBCurr, 1760 OMX_INT *pDstCost, 1761 OMX_U16 *pDstBlockSAD) 1762 { 1763 OMX_U32 Cost, i, IntraFlag = 1; 1764 OMXVCM4P10MEParams *pMEParams; 1765 1766 /* check for argument error */ 1767 armRetArgErrIf(pSrcCurrBuf == NULL, OMX_Sts_BadArgErr) 1768 armRetArgErrIf(pSrcRefBufList == NULL, OMX_Sts_BadArgErr) 1769 armRetArgErrIf(pSrcRecBuf == NULL, OMX_Sts_BadArgErr) 1770 armRetArgErrIf(pRefRect == NULL, OMX_Sts_BadArgErr) 1771 armRetArgErrIf(pCurrPointPos == NULL, OMX_Sts_BadArgErr) 1772 armRetArgErrIf(pMESpec == NULL, OMX_Sts_BadArgErr) 1773 armRetArgErrIf(pMBInter == NULL, OMX_Sts_BadArgErr) 1774 armRetArgErrIf(pMBIntra == NULL, OMX_Sts_BadArgErr) 1775 armRetArgErrIf(pSrcDstMBCurr == NULL, OMX_Sts_BadArgErr) 1776 armRetArgErrIf(pDstCost == NULL, OMX_Sts_BadArgErr) 1777 armRetArgErrIf(SrcRefStep <= 0 || SrcRefStep & 15, OMX_Sts_BadArgErr) 1778 armRetArgErrIf(SrcRecStep <= 0 || SrcRecStep & 15, OMX_Sts_BadArgErr) 1779 armRetArgErrIf(SrcCurrStep <= 0 || SrcCurrStep & 15, OMX_Sts_BadArgErr) 1780 1781 armRetArgErrIf(armNot16ByteAligned(pSrcCurrBuf), OMX_Sts_BadArgErr) 1782 armRetArgErrIf(armNot16ByteAligned(pSrcRecBuf), OMX_Sts_BadArgErr) 1783 1784 for (i = 0; i < ARM_VCM4P10_MAX_FRAMES; i++) 1785 { 1786 armRetArgErrIf(pSrcRefBufList [i] != NULL && 1787 armNot16ByteAligned(pSrcRefBufList [i]), OMX_Sts_BadArgErr) 1788 1789 /* Check if current MB needs INTER cost calculations */ 1790 if (pSrcRefBufList [i] != NULL && IntraFlag == 1) 1791 { 1792 IntraFlag = 0; 1793 } 1794 } 1795 1796 *pDstCost = ARM_VCM4P10_MAX_COST; 1797 /* 1798 * Inter cost calculations 1799 */ 1800 1801 /* check this MB can be Inter */ 1802 if (IntraFlag != 1) 1803 { 1804 armVCM4P10_InterMEMB( 1805 pSrcCurrBuf, 1806 SrcCurrStep, 1807 pSrcRefBufList, 1808 SrcRefStep, 1809 pRefRect, 1810 pCurrPointPos, 1811 Lambda, 1812 pMESpec, 1813 pMBInter, 1814 pSrcDstMBCurr, 1815 &Cost 1816 ); 1817 1818 *pDstCost = Cost; 1819 } 1820 1821 pMEParams = (OMXVCM4P10MEParams *)pMESpec; 1822 1823 if (pMEParams->intraEnable4x4 == 1) 1824 { 1825 /* 1826 * Intra 4x4 cost calculations 1827 */ 1828 armVCM4P10_Intra4x4Estimation( 1829 pSrcCurrBuf, 1830 SrcCurrStep, 1831 pSrcRecBuf, 1832 SrcRecStep, 1833 pMBIntra, 1834 pSrcDstMBCurr, 1835 &Cost 1836 ); 1837 1838 if (Cost <= *pDstCost) 1839 { 1840 *pDstCost = Cost; 1841 pSrcDstMBCurr->mbType = OMX_VC_INTRA_4x4; 1842 1843 } 1844 1845 } 1846 1847 /* 1848 * Cost for Intra 16x16 mode 1849 */ 1850 1851 armVCM4P10_Intra16x16Estimation( 1852 pSrcCurrBuf, 1853 SrcCurrStep, 1854 pSrcRecBuf, 1855 SrcRecStep, 1856 pCurrPointPos, 1857 pMBInter, 1858 pMBIntra, 1859 pSrcDstMBCurr, 1860 &Cost 1861 ); 1862 1863 if (Cost <= *pDstCost) 1864 { 1865 *pDstCost = Cost; 1866 pSrcDstMBCurr->mbType = OMX_VC_INTRA_16x16; 1867 } 1868 1869 /* 1870 * Update pDstBlockSAD to max value 1871 */ 1872 armVCM4P10_CalculateBlockSAD( pSrcDstMBCurr, 1873 pSrcCurrBuf, 1874 SrcCurrStep, 1875 pSrcRefBufList, 1876 SrcRefStep, 1877 pSrcRecBuf, 1878 SrcRecStep, 1879 pRefRect, 1880 pCurrPointPos, 1881 pMBInter, 1882 pMBIntra, 1883 pDstBlockSAD); 1884 1885 1886 return OMX_Sts_NoErr; 1887 } 1888 1889 1890 /***************************************************************************** 1891 * END OF FILE 1892 *****************************************************************************/ 1893