1 /* ---------------------------------------------------------------- 2 * 3 * 4 * File Name: omxVCM4P10_PredictIntra_4x4.c 5 * OpenMAX DL: v1.0.2 6 * Revision: 9641 7 * Date: Thursday, February 7, 2008 8 * 9 * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved. 10 * 11 * 12 * 13 * H.264 4x4 intra prediction module 14 * 15 */ 16 17 #include "omxtypes.h" 18 #include "armOMX.h" 19 #include "omxVC.h" 20 21 #include "armCOMM.h" 22 #include "armVC.h" 23 24 /** 25 * Function: omxVCM4P10_PredictIntra_4x4 (6.3.3.1.1) 26 * 27 * Description: 28 * Perform Intra_4x4 prediction for luma samples. If the upper-right block is 29 * not available, then duplication work should be handled inside the function. 30 * Users need not define them outside. 31 * 32 * Input Arguments: 33 * 34 * pSrcLeft - Pointer to the buffer of 4 left pixels: 35 * p[x, y] (x = -1, y = 0..3) 36 * pSrcAbove - Pointer to the buffer of 8 above pixels: 37 * p[x,y] (x = 0..7, y =-1); 38 * must be aligned on a 4-byte boundary. 39 * pSrcAboveLeft - Pointer to the above left pixels: p[x,y] (x = -1, y = -1) 40 * leftStep - Step of left pixel buffer; must be a multiple of 4. 41 * dstStep - Step of the destination buffer; must be a multiple of 4. 42 * predMode - Intra_4x4 prediction mode. 43 * availability - Neighboring 4x4 block availability flag, refer to 44 * "Neighboring Macroblock Availability" . 45 * 46 * Output Arguments: 47 * 48 * pDst - Pointer to the destination buffer; must be aligned on a 4-byte 49 * boundary. 50 * 51 * Return Value: 52 * If the function runs without error, it returns OMX_Sts_NoErr. 53 * If one of the following cases occurs, the function returns 54 * OMX_Sts_BadArgErr: 55 * pDst is NULL. 56 * dstStep < 4, or dstStep is not a multiple of 4. 57 * leftStep is not a multiple of 4. 58 * predMode is not in the valid range of enumeration 59 * OMXVCM4P10Intra4x4PredMode. 60 * predMode is OMX_VC_4x4_VERT, but availability doesn't set OMX_VC_UPPER 61 * indicating p[x,-1] (x = 0..3) is not available. 62 * predMode is OMX_VC_4x4_HOR, but availability doesn't set OMX_VC_LEFT 63 * indicating p[-1,y] (y = 0..3) is not available. 64 * predMode is OMX_VC_4x4_DIAG_DL, but availability doesn't set 65 * OMX_VC_UPPER indicating p[x, 1] (x = 0..3) is not available. 66 * predMode is OMX_VC_4x4_DIAG_DR, but availability doesn't set 67 * OMX_VC_UPPER_LEFT or OMX_VC_UPPER or OMX_VC_LEFT indicating 68 * p[x,-1] (x = 0..3), or p[-1,y] (y = 0..3) or p[-1,-1] is not 69 * available. 70 * predMode is OMX_VC_4x4_VR, but availability doesn't set 71 * OMX_VC_UPPER_LEFT or OMX_VC_UPPER or OMX_VC_LEFT indicating 72 * p[x,-1] (x = 0..3), or p[-1,y] (y = 0..3) or p[-1,-1] is not 73 * available. 74 * predMode is OMX_VC_4x4_HD, but availability doesn't set 75 * OMX_VC_UPPER_LEFT or OMX_VC_UPPER or OMX_VC_LEFT indicating 76 * p[x,-1] (x = 0..3), or p[-1,y] (y = 0..3) or p[-1,-1] is not 77 * available. 78 * predMode is OMX_VC_4x4_VL, but availability doesn't set OMX_VC_UPPER 79 * indicating p[x,-1] (x = 0..3) is not available. 80 * predMode is OMX_VC_4x4_HU, but availability doesn't set OMX_VC_LEFT 81 * indicating p[-1,y] (y = 0..3) is not available. 82 * availability sets OMX_VC_UPPER, but pSrcAbove is NULL. 83 * availability sets OMX_VC_LEFT, but pSrcLeft is NULL. 84 * availability sets OMX_VC_UPPER_LEFT, but pSrcAboveLeft is NULL. 85 * either pSrcAbove or pDst is not aligned on a 4-byte boundary. 86 * 87 * Note: 88 * pSrcAbove, pSrcAbove, pSrcAboveLeft may be invalid pointers if 89 * they are not used by intra prediction as implied in predMode. 90 * 91 */ 92 93 OMXResult omxVCM4P10_PredictIntra_4x4( 94 const OMX_U8* pSrcLeft, 95 const OMX_U8 *pSrcAbove, 96 const OMX_U8 *pSrcAboveLeft, 97 OMX_U8* pDst, 98 OMX_INT leftStep, 99 OMX_INT dstStep, 100 OMXVCM4P10Intra4x4PredMode predMode, 101 OMX_S32 availability 102 ) 103 { 104 int x, y; 105 OMX_U8 pTmp[10]; 106 107 armRetArgErrIf(pDst == NULL, OMX_Sts_BadArgErr); 108 armRetArgErrIf((leftStep % 4) != 0, OMX_Sts_BadArgErr); 109 armRetArgErrIf((dstStep % 4) != 0, OMX_Sts_BadArgErr); 110 armRetArgErrIf((dstStep < 4), OMX_Sts_BadArgErr); 111 armRetArgErrIf(armNot4ByteAligned(pSrcAbove), OMX_Sts_BadArgErr); 112 armRetArgErrIf(armNot4ByteAligned(pDst), OMX_Sts_BadArgErr); 113 armRetArgErrIf((availability & OMX_VC_UPPER) && pSrcAbove == NULL, OMX_Sts_BadArgErr); 114 armRetArgErrIf((availability & OMX_VC_LEFT ) && pSrcLeft == NULL, OMX_Sts_BadArgErr); 115 armRetArgErrIf((availability & OMX_VC_UPPER_LEFT) && pSrcAboveLeft == NULL, OMX_Sts_BadArgErr); 116 armRetArgErrIf(predMode==OMX_VC_4X4_VERT && !(availability & OMX_VC_UPPER), OMX_Sts_BadArgErr); 117 armRetArgErrIf(predMode==OMX_VC_4X4_HOR && !(availability & OMX_VC_LEFT), OMX_Sts_BadArgErr); 118 armRetArgErrIf(predMode==OMX_VC_4X4_DIAG_DL && !(availability & OMX_VC_UPPER), OMX_Sts_BadArgErr); 119 armRetArgErrIf(predMode==OMX_VC_4X4_DIAG_DR && !(availability & OMX_VC_UPPER), OMX_Sts_BadArgErr); 120 armRetArgErrIf(predMode==OMX_VC_4X4_DIAG_DR && !(availability & OMX_VC_UPPER_LEFT), OMX_Sts_BadArgErr); 121 armRetArgErrIf(predMode==OMX_VC_4X4_DIAG_DR && !(availability & OMX_VC_LEFT), OMX_Sts_BadArgErr); 122 armRetArgErrIf(predMode==OMX_VC_4X4_VR && !(availability & OMX_VC_UPPER), OMX_Sts_BadArgErr); 123 armRetArgErrIf(predMode==OMX_VC_4X4_VR && !(availability & OMX_VC_UPPER_LEFT), OMX_Sts_BadArgErr); 124 armRetArgErrIf(predMode==OMX_VC_4X4_VR && !(availability & OMX_VC_LEFT), OMX_Sts_BadArgErr); 125 armRetArgErrIf(predMode==OMX_VC_4X4_HD && !(availability & OMX_VC_UPPER), OMX_Sts_BadArgErr); 126 armRetArgErrIf(predMode==OMX_VC_4X4_HD && !(availability & OMX_VC_UPPER_LEFT), OMX_Sts_BadArgErr); 127 armRetArgErrIf(predMode==OMX_VC_4X4_HD && !(availability & OMX_VC_LEFT), OMX_Sts_BadArgErr); 128 armRetArgErrIf(predMode==OMX_VC_4X4_VL && !(availability & OMX_VC_UPPER), OMX_Sts_BadArgErr); 129 armRetArgErrIf(predMode==OMX_VC_4X4_HU && !(availability & OMX_VC_LEFT), OMX_Sts_BadArgErr); 130 armRetArgErrIf((unsigned)predMode > OMX_VC_4X4_HU, OMX_Sts_BadArgErr); 131 132 /* Note: This code must not read the pSrc arrays unless the corresponding 133 * block is marked as available. If the block is not avaibable then pSrc 134 * may not be a valid pointer. 135 * 136 * Note: To make the code more readable we refer to the neighbouring pixels 137 * in variables named as below: 138 * 139 * UL U0 U1 U2 U3 U4 U5 U6 U7 140 * L0 xx xx xx xx 141 * L1 xx xx xx xx 142 * L2 xx xx xx xx 143 * L3 xx xx xx xx 144 */ 145 146 #define UL pSrcAboveLeft[0] 147 #define U0 pSrcAbove[0] 148 #define U1 pSrcAbove[1] 149 #define U2 pSrcAbove[2] 150 #define U3 pSrcAbove[3] 151 #define U4 pSrcAbove[4] 152 #define U5 pSrcAbove[5] 153 #define U6 pSrcAbove[6] 154 #define U7 pSrcAbove[7] 155 #define L0 pSrcLeft[0*leftStep] 156 #define L1 pSrcLeft[1*leftStep] 157 #define L2 pSrcLeft[2*leftStep] 158 #define L3 pSrcLeft[3*leftStep] 159 160 switch (predMode) 161 { 162 case OMX_VC_4X4_VERT: 163 for (y=0; y<4; y++) 164 { 165 pDst[y*dstStep+0] = U0; 166 pDst[y*dstStep+1] = U1; 167 pDst[y*dstStep+2] = U2; 168 pDst[y*dstStep+3] = U3; 169 } 170 break; 171 172 case OMX_VC_4X4_HOR: 173 for (x=0; x<4; x++) 174 { 175 pDst[0*dstStep+x] = L0; 176 pDst[1*dstStep+x] = L1; 177 pDst[2*dstStep+x] = L2; 178 pDst[3*dstStep+x] = L3; 179 } 180 break; 181 182 case OMX_VC_4X4_DC: 183 /* This can always be used even if no blocks available */ 184 armVCM4P10_PredictIntraDC4x4(pSrcLeft, pSrcAbove, pDst, leftStep, dstStep, availability); 185 break; 186 187 case OMX_VC_4X4_DIAG_DL: 188 pTmp[0] = (OMX_U8)((U0 + 2*U1 + U2 + 2)>>2); 189 pTmp[1] = (OMX_U8)((U1 + 2*U2 + U3 + 2)>>2); 190 if (availability & OMX_VC_UPPER_RIGHT) 191 { 192 pTmp[2] = (OMX_U8)((U2 + 2*U3 + U4 + 2)>>2); 193 pTmp[3] = (OMX_U8)((U3 + 2*U4 + U5 + 2)>>2); 194 pTmp[4] = (OMX_U8)((U4 + 2*U5 + U6 + 2)>>2); 195 pTmp[5] = (OMX_U8)((U5 + 2*U6 + U7 + 2)>>2); 196 pTmp[6] = (OMX_U8)((U6 + 3*U7 + 2)>>2); 197 } 198 else 199 { 200 pTmp[2] = (OMX_U8)((U2 + 3*U3 + 2)>>2); 201 pTmp[3] = U3; 202 pTmp[4] = U3; 203 pTmp[5] = U3; 204 pTmp[6] = U3; 205 } 206 for (y=0; y<4; y++) 207 { 208 for (x=0; x<4; x++) 209 { 210 pDst[y*dstStep+x] = pTmp[x+y]; 211 } 212 } 213 break; 214 215 case OMX_VC_4X4_DIAG_DR: 216 /* x-y = -3, -2, -1, 0, 1, 2, 3 */ 217 pTmp[0] = (OMX_U8)((L1 + 2*L2 + L3 + 2)>>2); 218 pTmp[1] = (OMX_U8)((L0 + 2*L1 + L2 + 2)>>2); 219 pTmp[2] = (OMX_U8)((UL + 2*L0 + L1 + 2)>>2); 220 pTmp[3] = (OMX_U8)((U0 + 2*UL + L0 + 2)>>2); 221 pTmp[4] = (OMX_U8)((U1 + 2*U0 + UL + 2)>>2); 222 pTmp[5] = (OMX_U8)((U2 + 2*U1 + U0 + 2)>>2); 223 pTmp[6] = (OMX_U8)((U3 + 2*U2 + U1 + 2)>>2); 224 for (y=0; y<4; y++) 225 { 226 for (x=0; x<4; x++) 227 { 228 pDst[y*dstStep+x] = pTmp[3+x-y]; 229 } 230 } 231 break; 232 233 case OMX_VC_4X4_VR: 234 /* zVR=2x-y = -3, -2, -1, 0, 1, 2, 3, 4, 5, 6 235 * x-(y>>1) = -1, -1, 0, 0, 1, 1, 2, 2, 3, 3 236 * y = 3, 2, ?, ?, ?, ?, ?, ?, 1, 0 237 */ 238 pTmp[0] = (OMX_U8)((L2 + 2*L1 + L0 + 2)>>2); 239 pTmp[1] = (OMX_U8)((L1 + 2*L0 + UL + 2)>>2); 240 pTmp[2] = (OMX_U8)((L0 + 2*UL + U0 + 2)>>2); 241 pTmp[3] = (OMX_U8)((UL + U0 + 1)>>1); 242 pTmp[4] = (OMX_U8)((UL + 2*U0 + U1 + 2)>>2); 243 pTmp[5] = (OMX_U8)((U0 + U1 + 1)>>1); 244 pTmp[6] = (OMX_U8)((U0 + 2*U1 + U2 + 2)>>2); 245 pTmp[7] = (OMX_U8)((U1 + U2 + 1)>>1); 246 pTmp[8] = (OMX_U8)((U1 + 2*U2 + U3 + 2)>>2); 247 pTmp[9] = (OMX_U8)((U2 + U3 + 1)>>1); 248 for (y=0; y<4; y++) 249 { 250 for (x=0; x<4; x++) 251 { 252 pDst[y*dstStep+x] = pTmp[3+2*x-y]; 253 } 254 } 255 break; 256 257 case OMX_VC_4X4_HD: 258 /* zHD=2y-x = -3 -2 -1 0 1 2 3 4 5 6 259 * y-(x>>1) = -1 -1 0 0 1 1 2 2 3 3 260 * x = 3 2 1 0 261 */ 262 pTmp[0] = (OMX_U8)((U2 + 2*U1 + U0 + 2)>>2); 263 pTmp[1] = (OMX_U8)((U1 + 2*U0 + UL + 2)>>2); 264 pTmp[2] = (OMX_U8)((U0 + 2*UL + L0 + 2)>>2); 265 pTmp[3] = (OMX_U8)((UL + L0 + 1)>>1); 266 pTmp[4] = (OMX_U8)((UL + 2*L0 + L1 + 2)>>2); 267 pTmp[5] = (OMX_U8)((L0 + L1 + 1)>>1); 268 pTmp[6] = (OMX_U8)((L0 + 2*L1 + L2 + 2)>>2); 269 pTmp[7] = (OMX_U8)((L1 + L2 + 1)>>1); 270 pTmp[8] = (OMX_U8)((L1 + 2*L2 + L3 + 2)>>2); 271 pTmp[9] = (OMX_U8)((L2 + L3 + 1)>>1); 272 for (y=0; y<4; y++) 273 { 274 for (x=0; x<4; x++) 275 { 276 pDst[y*dstStep+x] = pTmp[3+2*y-x]; 277 } 278 } 279 break; 280 281 case OMX_VC_4X4_VL: 282 /* Note: x+(y>>1) = (2*x+y)>>1 283 * 2x+y = 0 1 2 3 4 5 6 7 8 9 284 */ 285 pTmp[0] = (OMX_U8)((U0 + U1 + 1)>>1); 286 pTmp[1] = (OMX_U8)((U0 + 2*U1 + U2 + 2)>>2); 287 pTmp[2] = (OMX_U8)((U1 + U2 + 1)>>1); 288 pTmp[3] = (OMX_U8)((U1 + 2*U2 + U3 + 2)>>2); 289 pTmp[4] = (OMX_U8)((U2 + U3 + 1)>>1); 290 if (availability & OMX_VC_UPPER_RIGHT) 291 { 292 pTmp[5] = (OMX_U8)((U2 + 2*U3 + U4 + 2)>>2); 293 pTmp[6] = (OMX_U8)((U3 + U4 + 1)>>1); 294 pTmp[7] = (OMX_U8)((U3 + 2*U4 + U5 + 2)>>2); 295 pTmp[8] = (OMX_U8)((U4 + U5 + 1)>>1); 296 pTmp[9] = (OMX_U8)((U4 + 2*U5 + U6 + 2)>>2); 297 } 298 else 299 { 300 pTmp[5] = (OMX_U8)((U2 + 3*U3 + 2)>>2); 301 pTmp[6] = U3; 302 pTmp[7] = U3; 303 pTmp[8] = U3; 304 pTmp[9] = U3; 305 } 306 for (y=0; y<4; y++) 307 { 308 for (x=0; x<4; x++) 309 { 310 pDst[y*dstStep+x] = pTmp[2*x+y]; 311 } 312 } 313 break; 314 315 case OMX_VC_4X4_HU: 316 /* zHU = x+2*y */ 317 pTmp[0] = (OMX_U8)((L0 + L1 + 1)>>1); 318 pTmp[1] = (OMX_U8)((L0 + 2*L1 + L2 + 2)>>2); 319 pTmp[2] = (OMX_U8)((L1 + L2 + 1)>>1); 320 pTmp[3] = (OMX_U8)((L1 + 2*L2 + L3 + 2)>>2); 321 pTmp[4] = (OMX_U8)((L2 + L3 + 1)>>1); 322 pTmp[5] = (OMX_U8)((L2 + 3*L3 + 2)>>2); 323 pTmp[6] = L3; 324 pTmp[7] = L3; 325 pTmp[8] = L3; 326 pTmp[9] = L3; 327 for (y=0; y<4; y++) 328 { 329 for (x=0; x<4; x++) 330 { 331 pDst[y*dstStep+x] = pTmp[x+2*y]; 332 } 333 } 334 break; 335 } 336 337 return OMX_Sts_NoErr; 338 } 339