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