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