📄 omxvcm4p10_motionestimationmb.c
字号:
/** x * * File Name: omxVCM4P10_MotionEstimationMB.c * OpenMAX DL: v1.0.2 * Revision: 10586 * Date: Wednesday, March 5, 2008 * * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved. * * * Description: * This function perform MB level motion estimation * */#include "omxtypes.h"#include "armOMX.h"#include "omxVC.h"#include "armCOMM.h"#include "armVC.h"#define ARM_VCM4P10_MAX_FRAMES (15)#define ARM_VCM4P10_MAX_4x4_SAD (0xffff)#define ARM_VCM4P10_MAX_MODE_VALUE (0xffffffff)#define ARM_VCM4P10_MAX_MODES (16)#define ARM_VCM4P10_MB_BLOCK_SIZE (16)#define ARM_VCM4P10_MEDIAN(a,b,c) (a>b?a>c?b>c?b:c:a:b>c?a>c?a:c:b)#define ARM_VCM4P10_SHIFT_QP (12)#define ARM_VCM4P10_MVPRED_MEDIAN (0)#define ARM_VCM4P10_MVPRED_L (1)#define ARM_VCM4P10_MVPRED_U (2)#define ARM_VCM4P10_MVPRED_UR (3)#define ARM_VCM4P10_MB_BLOCK_SIZE (16)#define ARM_VCM4P10_BLOCK_SIZE (4)#define ARM_VCM4P10_MAX_COST (1 << 30)#define ARM_VCM4P10_INVALID_BLOCK (-2)/** * Function: armVCM4P10_CalculateBlockSAD * * Description: * Calculate SAD value for the selected MB encoding mode and update * pDstBlockSAD parameter. These SAD values are calculated 4x4 blocks at * a time and in the scan order. * * Remarks: * * Parameters: * [in] pSrcMBInfo - * [in] pSrcCurrBuf - * [in] SrcCurrStep - * [in] pSrcRefBufList- * [in] SrcRefStep - * [in] pSrcRecBuf - * [in] SrcRecStep - * [in] pRefRect - * [in] pCurrPointPos - * [in] Lambda - * [in] pMESpec - * [in] pMBInter - * [in] pMBIntra - * [out] pDstBlockSAD - pointer to 16 element array for SAD corresponding to 4x4 blocks * Return Value: * None * */static OMXResult armVCM4P10_CalculateBlockSAD( OMXVCM4P10MBInfo *pSrcMBInfo, const OMX_U8 *pSrcCurrBuf, OMX_S32 SrcCurrStep, const OMX_U8 *pSrcRefBufList[ARM_VCM4P10_MAX_FRAMES], OMX_S32 SrcRefStep, const OMX_U8 *pSrcRecBuf, OMX_S32 SrcRecStep, const OMXRect *pRefRect, const OMXVCM4P2Coordinate *pCurrPointPos, const OMXVCM4P10MBInfoPtr *pMBInter, const OMXVCM4P10MBInfoPtr *pMBIntra, OMX_U16 *pDstBlockSAD){ OMX_INT InvalidSAD = 0; OMX_INT i; OMX_U8 Buffer [16*16 + 15]; OMX_U8 *pTempDstBuf; OMX_S32 TempDstStep; OMX_U8 *pTempRefBuf; OMX_S32 TempRefStep; /* Temporary buffer to store the predicted mb coefficients */ pTempDstBuf = armAlignTo16Bytes(Buffer); TempDstStep = 16; /* Update pDstBlockSAD if MB is a valid type */ if (pSrcMBInfo) { OMX_U32 Width=0, Height=0, MaxXPart, MaxYPart,MaxSubXPart,MaxSubYPart; /* Depending on type of MB, do prediction and fill temp buffer */ switch (pSrcMBInfo->mbType) { case OMX_VC_P_16x16: Width = 16; Height = 16; break; case OMX_VC_P_16x8: Width = 16; Height = 8; break; case OMX_VC_P_8x16: Width = 8; Height = 16; break; case OMX_VC_P_8x8: Width = 8; Height = 8; break; case OMX_VC_INTRA_4x4: { /* Create predicted MB Intra4x4 mode */ OMX_S32 PredIntra4x4Mode [5][9]; OMX_S32 x, y, Block8x8, Block4x4, BlockX, BlockY; OMX_U8 pSrcYBuff [(16*3)*(16*2)]; OMX_U8 *pSrcY; OMX_S32 StepSrcY; OMX_S32 availability; for (y = 0; y < 5; y++) { for (x = 0; x < 9; x++) { /* * Initialize with value of ARM_VCM4P10_INVALID_BLOCK, to mean this * 4x4 block is not available */ PredIntra4x4Mode [y][x] = ARM_VCM4P10_INVALID_BLOCK; } } /* Replace ARM_VCM4P10_INVALID_BLOCK value with available MBs values*/ for (x = 0; x < 4; x++) { /* Store values of b0, b1, b2, b3 */ if (pMBIntra[1] != NULL) { PredIntra4x4Mode [0][x + 1] = pMBIntra[1]->pIntra4x4PredMode[3*4 + x]; } /* Store values of d0, d1, d2, d3 */ if (pMBIntra[3] != NULL) { PredIntra4x4Mode [0][x + 5] = pMBIntra[3]->pIntra4x4PredMode[3*4 + x]; } } /* Store values of c3 */ if (pMBIntra[2] != NULL) { PredIntra4x4Mode [0][0] = pMBIntra[2]->pIntra4x4PredMode[15]; } for (y = 0; y < 4; y++) { /* Store values of a0, a1, a2, a3 */ if (pMBIntra[0] != NULL) { PredIntra4x4Mode [y + 1][0] = pMBIntra[0]->pIntra4x4PredMode[y*4 + 3]; } } /* * Update neighbouring Pred mode array which will be used for * prediction of Intra4x4 modes. */ pSrcY = pSrcYBuff; StepSrcY = 16 * 3; for (y = 0; y < (16 * 2); y++) { for (x = 0; x < (16 * 3); x++) { pSrcY [StepSrcY * y + x] = pSrcRecBuf [SrcRecStep * (y - 16) + x - 16]; } } /* for each 8x8 block */ for (Block8x8 = 0; Block8x8 < 4; Block8x8++) { /* for each 4x4 block inside 8x8 block */ for (Block4x4 = 0; Block4x4 < 4; Block4x4++) { /* Get block cordinates from 8x8 block index and 4x4 block index */ BlockX = ((Block8x8 & 1) << 1) + (Block4x4 & 1); BlockY = ((Block8x8 >> 1) << 1) + (Block4x4 >> 1); /* Add offset to point to start of current MB in the array pIntra4x4PredMode */ x = BlockX + 1; y = BlockY + 1; availability = 0; /* Check for availability of LEFT Block */ if (PredIntra4x4Mode [y][x - 1] != ARM_VCM4P10_INVALID_BLOCK) { availability |= OMX_VC_LEFT; } /* Check for availability of UPPER Block */ if (PredIntra4x4Mode [y - 1][x] != ARM_VCM4P10_INVALID_BLOCK) { availability |= OMX_VC_UPPER; } /* Check for availability of UPPER LEFT Block */ if (PredIntra4x4Mode [y - 1][x - 1] != ARM_VCM4P10_INVALID_BLOCK) { availability |= OMX_VC_UPPER_LEFT; } PredIntra4x4Mode [y][x] = pSrcMBInfo->pIntra4x4PredMode[BlockY*4+BlockX]; x = BlockX * 4; y = BlockY * 4; pSrcY = pSrcYBuff + 16 * StepSrcY + 16 + y * StepSrcY + x; omxVCM4P10_PredictIntra_4x4( pSrcY - 1, pSrcY - StepSrcY, pSrcY - StepSrcY - 1, pTempDstBuf + x + y * TempDstStep, StepSrcY, TempDstStep, pSrcMBInfo->pIntra4x4PredMode[BlockY*4+BlockX], availability); for (BlockY=0;BlockY<4;BlockY++) { for(BlockX=0;BlockX<4;BlockX++) { pSrcY [BlockY * StepSrcY + BlockX] = (OMX_U8)(*(pTempDstBuf + x + y * TempDstStep + BlockY * TempDstStep + BlockX)); } } } } break; } case OMX_VC_INTRA_16x16: { OMX_U32 MBPosX = pCurrPointPos->x >> 4; OMX_U32 MBPosY = pCurrPointPos->y >> 4; OMX_U32 availability = 0; /* Check for availability of LEFT MB */ if ((MBPosX != 0) && (pMBIntra [0] != 0 || pMBInter [0] != 0)) { availability |= OMX_VC_LEFT; } /* Check for availability of UP MB */ if ((MBPosY != 0) && (pMBIntra [1] != 0 || pMBInter [1] != 0)) { availability |= OMX_VC_UPPER; } /* Check for availability of UP-LEFT MB */ if ((MBPosX > 0) && (MBPosY > 0) && (pMBIntra [2] != 0 || pMBInter [2] != 0)) { availability |= OMX_VC_UPPER_LEFT; } omxVCM4P10_PredictIntra_16x16( pSrcRecBuf - 1, pSrcRecBuf - SrcRecStep, pSrcRecBuf - SrcRecStep - 1, pTempDstBuf, SrcRecStep, TempDstStep, pSrcMBInfo->Intra16x16PredMode, availability); break; } case OMX_VC_INTER_SKIP: case OMX_VC_PREF0_8x8: case OMX_VC_INTRA_PCM: default: /* These cases will update pDstBlockSAD with MAX value */ InvalidSAD = 1; break; } /* INTER MB */ if ((pSrcMBInfo->mbType == OMX_VC_P_16x16) || (pSrcMBInfo->mbType == OMX_VC_P_8x16) || (pSrcMBInfo->mbType == OMX_VC_P_16x8) || (pSrcMBInfo->mbType == OMX_VC_P_8x8)) { const OMX_U8 *pTempSrcBuf; OMX_S32 TempSrcStep; OMX_S32 mvx,mvy; OMX_U32 PartX, PartY, SubPartX, SubPartY; TempSrcStep = SrcRefStep; MaxXPart = 16/Width; MaxYPart = 16/Height; for (PartY = 0; PartY < MaxYPart; PartY++) { for (PartX = 0; PartX < MaxXPart; PartX++) { pTempSrcBuf = pSrcRefBufList[pSrcMBInfo->pRefL0Idx[PartY * 2 + PartX]]; if (MaxXPart == 2 && MaxYPart == 2) { switch (pSrcMBInfo->subMBType[PartY*2+PartX]) { case OMX_VC_SUB_P_8x8: Width = 8; Height = 8; break; case OMX_VC_SUB_P_8x4: Width = 8; Height = 4; break; case OMX_VC_SUB_P_4x8: Width = 4; Height = 8; break; case OMX_VC_SUB_P_4x4: Width = 4; Height = 4; break; default: /* Default */ Width = 4; Height = 4; break; } MaxSubXPart = 8/Width; MaxSubYPart = 8/Height; for (SubPartY = 0; SubPartY < MaxSubYPart; SubPartY++) { for (SubPartX = 0; SubPartX < MaxSubXPart; SubPartX++) { mvx = pSrcMBInfo->pMV0 [2*PartY + SubPartY][2*PartX + SubPartX].dx; mvy = pSrcMBInfo->pMV0 [2*PartY + SubPartY][2*PartX + SubPartX].dy; armVCM4P10_Interpolate_Luma( pTempSrcBuf + (8*PartX + 4*SubPartX + (mvx/4)) + (8*PartY + 4*SubPartY + (mvy/4)) * TempSrcStep, TempSrcStep, pTempDstBuf + (8*PartX + 4*SubPartX) + (8*PartY + 4*SubPartY) * TempDstStep, TempDstStep, Width, Height, mvx & 3, mvy & 3 ); } } } else { mvx = pSrcMBInfo->pMV0 [2*PartY][2*PartX].dx; mvy = pSrcMBInfo->pMV0 [2*PartY][2*PartX].dy; armVCM4P10_Interpolate_Luma( pTempSrcBuf + (8*PartX + (mvx/4)) + (8*PartY + (mvy/4)) * TempSrcStep, TempSrcStep, pTempDstBuf + (8*PartX) + (8*PartY) * TempDstStep, TempDstStep, Width, Height, mvx & 3, mvy & 3 ); } } } } } else { InvalidSAD = 1; } /* Calculate SAD from predicted buffer */ if (!InvalidSAD) { OMX_U32 x8x8, y8x8, x4x4, y4x4, Block8x8, Block4x4; OMX_S32 SAD; pTempRefBuf = pTempDstBuf; TempRefStep = 16; /* SAD for each 4x4 block in scan order */ for (Block8x8 = 0; Block8x8 < 4; Block8x8++) { x8x8 = 8*(Block8x8 & 1); y8x8 = 8*(Block8x8 >> 1); for (Block4x4 = 0; Block4x4 < 4; Block4x4++) { x4x4 = 4*(Block4x4 & 1); y4x4 = 4*(Block4x4 >> 1); armVCCOMM_SAD( pSrcCurrBuf + (x8x8 + x4x4) + (y8x8 + y4x4) * SrcCurrStep, SrcCurrStep, pTempRefBuf + (x8x8 + x4x4) + (y8x8 + y4x4) * TempRefStep, TempRefStep, &SAD, 4, /* Height */ 4); /* Width */ *(pDstBlockSAD + 4 * Block8x8 + Block4x4) = (SAD < 0x7fff) ? (OMX_U16) SAD : ARM_VCM4P10_MAX_MODE_VALUE; } } } else { /* Fill SADs with max values and return*/ for (i = 0; i < 16; i++) { pDstBlockSAD [i] = ARM_VCM4P10_MAX_4x4_SAD; } } return OMX_Sts_NoErr;}/** * Function: armVCM4P10_Mode4x4Decision * * Description: * Intra 4x4 Mode decision by calculating cost for all possible modes and * choosing the best mode * * Remarks: * * Parameters: * [in] pSrcCurrBuf - Pointer to the start of current Macroblock * [in] SrcCurrStep - Step size of the pointer pSrcCurrBuf * [in/out] pSrcDstMBCurr - Pointer to the OMXVCM4P10MBInfo which will be updated for * field pIntra4x4PredMode of the current block. * [in] Block8x8 - Index 8x8 block in which current 4x4 block belongs * [in] Block4x4 - Index of current 4x4 block * [in/out] pPredIntra4x4SrcY - Pointer to current block location in buffer * with reconstructed values. This will be modified by this * function with best mode predicted values * [in] StepPredIntra4x4SrcY - Step size of the pointer pPredIntra4x4SrcY * [in] pIntra4x4PredMode - Array of Intra 4x4 prediction mode for the MB. * Current MB modes starts at [1,1]. * [in] pBestCost - Cost for the Best Intra 4x4 mode * Return Value: * None *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -