1 /* 2 * Copyright (C) 2007-2008 ARM Limited 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 */ 17 /** 18 * 19 * File Name: omxVCM4P10_BlockMatch_Quarter.c 20 * OpenMAX DL: v1.0.2 21 * Revision: 9641 22 * Date: Thursday, February 7, 2008 23 * 24 * 25 * 26 * 27 * Description: 28 * Contains modules for quater pel Block matching, 29 * 30 */ 31 32 #include "omxtypes.h" 33 #include "armOMX.h" 34 #include "omxVC.h" 35 36 #include "armVC.h" 37 #include "armCOMM.h" 38 39 40 /** 41 * Function: omxVCM4P10_BlockMatch_Quarter (6.3.5.2.3) 42 * 43 * Description: 44 * Performs a quarter-pel block match using results from a prior half-pel 45 * search. Returns the best MV and associated cost. This function estimates 46 * the quarter-pixel motion vector by interpolating the half-pel resolution 47 * motion vector referenced by the input parameter pSrcDstBestMV, i.e., the 48 * initial half-pel MV is generated externally. The function 49 * omxVCM4P10_BlockMatch_Half may be used for half-pel motion estimation. 50 * 51 * Input Arguments: 52 * 53 * pSrcOrgY - Pointer to the current position in original picture plane. If 54 * iBlockWidth==4, 4-byte alignment required. If iBlockWidth==8, 55 * 8-byte alignment required. If iBlockWidth==16, 16-byte alignment 56 * required. 57 * pSrcRefY - Pointer to the top-left corner of the co-located block in the 58 * reference picture If iBlockWidth==4, 4-byte alignment 59 * required. If iBlockWidth==8, 8-byte alignment required. If 60 * iBlockWidth==16, 16-byte alignment required. 61 * nSrcOrgStep - Stride of the original picture plane in terms of full 62 * pixels; must be a multiple of iBlockWidth. 63 * nSrcRefStep - Stride of the reference picture plane in terms of full 64 * pixels 65 * iBlockWidth - Width of the current block in terms of full pixels; must 66 * be equal to either 4, 8, or 16. 67 * iBlockHeight - Height of the current block in terms of full pixels; must 68 * be equal to either 4, 8, or 16. 69 * nLamda - Lamda factor, used to compute motion cost 70 * pMVPred - Predicted MV, represented in terms of 1/4-pel units; used to 71 * compute motion cost 72 * pSrcDstBestMV - The best MV resulting from a prior half-pel search, 73 * represented in terms of 1/4 pel units 74 * 75 * Output Arguments: 76 * 77 * pSrcDstBestMV - Best MV resulting from the quarter-pel search, expressed 78 * in terms of 1/4-pel units 79 * pBestCost - Motion cost associated with the best MV; computed as 80 * SAD+Lamda*BitsUsedByMV 81 * 82 * Return Value: 83 * OMX_Sts_NoErr, if the function runs without error. 84 * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs: 85 * - One of more of the following pointers is NULL: 86 * pSrcOrgY, pSrcRefY, pSrcDstBestMV, pMVPred, pBestCost 87 * - iBlockWidth or iBlockHeight are equal to values other than 4, 8, or 16. 88 * - Any alignment restrictions are violated 89 * 90 */ 91 92 OMXResult omxVCM4P10_BlockMatch_Quarter( 93 const OMX_U8* pSrcOrgY, 94 OMX_S32 nSrcOrgStep, 95 const OMX_U8* pSrcRefY, 96 OMX_S32 nSrcRefStep, 97 OMX_U8 iBlockWidth, 98 OMX_U8 iBlockHeight, 99 OMX_U32 nLamda, 100 const OMXVCMotionVector* pMVPred, 101 OMXVCMotionVector* pSrcDstBestMV, 102 OMX_S32* pBestCost 103 ) 104 { 105 /* Definitions and Initializations*/ 106 OMX_INT candSAD; 107 OMX_INT fromX, toX, fromY, toY; 108 /* Offset to the reference at the begining of the bounding box */ 109 const OMX_U8 *pTempSrcRefY, *pTempSrcOrgY; 110 OMX_S16 x, y; 111 OMXVCMotionVector diffMV, candMV, initialMV; 112 OMX_U8 interpolY[256]; 113 OMX_S32 pelPosX, pelPosY; 114 115 /* Argument error checks */ 116 armRetArgErrIf((iBlockWidth == 4) && (!armIs4ByteAligned(pSrcOrgY)), OMX_Sts_BadArgErr); 117 armRetArgErrIf((iBlockWidth == 8) && (!armIs8ByteAligned(pSrcOrgY)), OMX_Sts_BadArgErr); 118 armRetArgErrIf((iBlockWidth == 16) && (!armIs16ByteAligned(pSrcOrgY)), OMX_Sts_BadArgErr); 119 armRetArgErrIf((iBlockWidth == 4) && (!armIs4ByteAligned(pSrcRefY)), OMX_Sts_BadArgErr); 120 armRetArgErrIf((iBlockWidth == 8) && (!armIs8ByteAligned(pSrcRefY)), OMX_Sts_BadArgErr); 121 armRetArgErrIf((iBlockWidth == 16) && (!armIs16ByteAligned(pSrcRefY)), OMX_Sts_BadArgErr); 122 armRetArgErrIf((nSrcOrgStep % iBlockWidth), OMX_Sts_BadArgErr); 123 armRetArgErrIf(pSrcOrgY == NULL, OMX_Sts_BadArgErr); 124 armRetArgErrIf(pSrcRefY == NULL, OMX_Sts_BadArgErr); 125 armRetArgErrIf(pMVPred == NULL, OMX_Sts_BadArgErr); 126 armRetArgErrIf(pSrcDstBestMV == NULL, OMX_Sts_BadArgErr); 127 armRetArgErrIf(pBestCost == NULL, OMX_Sts_BadArgErr); 128 armRetArgErrIf(((iBlockWidth!=4)&&(iBlockWidth!=8)&&(iBlockWidth!=16)) , OMX_Sts_BadArgErr); 129 armRetArgErrIf(((iBlockHeight!=4)&&(iBlockHeight!=8)&&(iBlockHeight!=16)) , OMX_Sts_BadArgErr); 130 131 132 /* Check for valid region */ 133 fromX = 1; 134 toX = 1; 135 fromY = 1; 136 toY = 1; 137 138 /* Initialize to max value as a start point */ 139 *pBestCost = 0x7fffffff; 140 141 initialMV.dx = pSrcDstBestMV->dx; 142 initialMV.dy = pSrcDstBestMV->dy; 143 144 /* Looping on y- axis */ 145 for (y = -fromY; y <= toY; y++) 146 { 147 /* Looping on x- axis */ 148 for (x = -fromX; x <= toX; x++) 149 { 150 /* Positioning the pointer */ 151 pTempSrcRefY = pSrcRefY + (nSrcRefStep * (initialMV.dy/4)) + (initialMV.dx/4); 152 153 /* Calculating the fract pel position */ 154 pelPosX = (initialMV.dx % 4) + x; 155 if (pelPosX < 0) 156 { 157 pTempSrcRefY = pTempSrcRefY - 1; 158 pelPosX += 4; 159 } 160 pelPosY = (initialMV.dy % 4) + y; 161 if (pelPosY < 0) 162 { 163 pTempSrcRefY = pTempSrcRefY - (1 * nSrcRefStep); 164 pelPosY += 4; 165 } 166 167 pTempSrcOrgY = pSrcOrgY; 168 169 /* Prepare cand MV */ 170 candMV.dx = initialMV.dx + x; 171 candMV.dy = initialMV.dy + y; 172 173 /* Interpolate Quater pel for the current position*/ 174 armVCM4P10_Interpolate_Luma( 175 pTempSrcRefY, 176 nSrcRefStep, 177 interpolY, 178 iBlockWidth, 179 iBlockWidth, 180 iBlockHeight, 181 pelPosX, 182 pelPosY); 183 184 /* Calculate the SAD */ 185 armVCCOMM_SAD( 186 pTempSrcOrgY, 187 nSrcOrgStep, 188 interpolY, 189 iBlockWidth, 190 &candSAD, 191 iBlockHeight, 192 iBlockWidth); 193 194 diffMV.dx = candMV.dx - pMVPred->dx; 195 diffMV.dy = candMV.dy - pMVPred->dy; 196 197 /* Result calculations */ 198 armVCM4P10_CompareMotionCostToMV ( 199 candMV.dx, 200 candMV.dy, 201 diffMV, 202 candSAD, 203 pSrcDstBestMV, 204 nLamda, 205 pBestCost); 206 207 } /* End of x- axis */ 208 } /* End of y-axis */ 209 210 return OMX_Sts_NoErr; 211 212 } 213 214 /* End of file */ 215