| /* |
| * Copyright (C) 2007-2008 ARM Limited |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| */ |
| /* ---------------------------------------------------------------- |
| * |
| * |
| * File Name: omxVCM4P10_PredictIntra_4x4.c |
| * OpenMAX DL: v1.0.2 |
| * Revision: 9641 |
| * Date: Thursday, February 7, 2008 |
| * |
| * |
| * |
| * |
| * H.264 4x4 intra prediction module |
| * |
| */ |
| |
| #include "omxtypes.h" |
| #include "armOMX.h" |
| #include "omxVC.h" |
| |
| #include "armCOMM.h" |
| #include "armVC.h" |
| |
| /** |
| * Function: omxVCM4P10_PredictIntra_4x4 (6.3.3.1.1) |
| * |
| * Description: |
| * Perform Intra_4x4 prediction for luma samples. If the upper-right block is |
| * not available, then duplication work should be handled inside the function. |
| * Users need not define them outside. |
| * |
| * Input Arguments: |
| * |
| * pSrcLeft - Pointer to the buffer of 4 left pixels: |
| * p[x, y] (x = -1, y = 0..3) |
| * pSrcAbove - Pointer to the buffer of 8 above pixels: |
| * p[x,y] (x = 0..7, y =-1); |
| * must be aligned on a 4-byte boundary. |
| * pSrcAboveLeft - Pointer to the above left pixels: p[x,y] (x = -1, y = -1) |
| * leftStep - Step of left pixel buffer; must be a multiple of 4. |
| * dstStep - Step of the destination buffer; must be a multiple of 4. |
| * predMode - Intra_4x4 prediction mode. |
| * availability - Neighboring 4x4 block availability flag, refer to |
| * "Neighboring Macroblock Availability" . |
| * |
| * Output Arguments: |
| * |
| * pDst - Pointer to the destination buffer; must be aligned on a 4-byte |
| * boundary. |
| * |
| * Return Value: |
| * If the function runs without error, it returns OMX_Sts_NoErr. |
| * If one of the following cases occurs, the function returns |
| * OMX_Sts_BadArgErr: |
| * pDst is NULL. |
| * dstStep < 4, or dstStep is not a multiple of 4. |
| * leftStep is not a multiple of 4. |
| * predMode is not in the valid range of enumeration |
| * OMXVCM4P10Intra4x4PredMode. |
| * predMode is OMX_VC_4x4_VERT, but availability doesn't set OMX_VC_UPPER |
| * indicating p[x,-1] (x = 0..3) is not available. |
| * predMode is OMX_VC_4x4_HOR, but availability doesn't set OMX_VC_LEFT |
| * indicating p[-1,y] (y = 0..3) is not available. |
| * predMode is OMX_VC_4x4_DIAG_DL, but availability doesn't set |
| * OMX_VC_UPPER indicating p[x, 1] (x = 0..3) is not available. |
| * predMode is OMX_VC_4x4_DIAG_DR, but availability doesn't set |
| * OMX_VC_UPPER_LEFT or OMX_VC_UPPER or OMX_VC_LEFT indicating |
| * p[x,-1] (x = 0..3), or p[-1,y] (y = 0..3) or p[-1,-1] is not |
| * available. |
| * predMode is OMX_VC_4x4_VR, but availability doesn't set |
| * OMX_VC_UPPER_LEFT or OMX_VC_UPPER or OMX_VC_LEFT indicating |
| * p[x,-1] (x = 0..3), or p[-1,y] (y = 0..3) or p[-1,-1] is not |
| * available. |
| * predMode is OMX_VC_4x4_HD, but availability doesn't set |
| * OMX_VC_UPPER_LEFT or OMX_VC_UPPER or OMX_VC_LEFT indicating |
| * p[x,-1] (x = 0..3), or p[-1,y] (y = 0..3) or p[-1,-1] is not |
| * available. |
| * predMode is OMX_VC_4x4_VL, but availability doesn't set OMX_VC_UPPER |
| * indicating p[x,-1] (x = 0..3) is not available. |
| * predMode is OMX_VC_4x4_HU, but availability doesn't set OMX_VC_LEFT |
| * indicating p[-1,y] (y = 0..3) is not available. |
| * availability sets OMX_VC_UPPER, but pSrcAbove is NULL. |
| * availability sets OMX_VC_LEFT, but pSrcLeft is NULL. |
| * availability sets OMX_VC_UPPER_LEFT, but pSrcAboveLeft is NULL. |
| * either pSrcAbove or pDst is not aligned on a 4-byte boundary. |
| * |
| * Note: |
| * pSrcAbove, pSrcAbove, pSrcAboveLeft may be invalid pointers if |
| * they are not used by intra prediction as implied in predMode. |
| * |
| */ |
| |
| OMXResult omxVCM4P10_PredictIntra_4x4( |
| const OMX_U8* pSrcLeft, |
| const OMX_U8 *pSrcAbove, |
| const OMX_U8 *pSrcAboveLeft, |
| OMX_U8* pDst, |
| OMX_INT leftStep, |
| OMX_INT dstStep, |
| OMXVCM4P10Intra4x4PredMode predMode, |
| OMX_S32 availability |
| ) |
| { |
| int x, y; |
| OMX_U8 pTmp[10]; |
| |
| armRetArgErrIf(pDst == NULL, OMX_Sts_BadArgErr); |
| armRetArgErrIf((leftStep % 4) != 0, OMX_Sts_BadArgErr); |
| armRetArgErrIf((dstStep % 4) != 0, OMX_Sts_BadArgErr); |
| armRetArgErrIf((dstStep < 4), OMX_Sts_BadArgErr); |
| armRetArgErrIf(armNot4ByteAligned(pSrcAbove), OMX_Sts_BadArgErr); |
| armRetArgErrIf(armNot4ByteAligned(pDst), OMX_Sts_BadArgErr); |
| armRetArgErrIf((availability & OMX_VC_UPPER) && pSrcAbove == NULL, OMX_Sts_BadArgErr); |
| armRetArgErrIf((availability & OMX_VC_LEFT ) && pSrcLeft == NULL, OMX_Sts_BadArgErr); |
| armRetArgErrIf((availability & OMX_VC_UPPER_LEFT) && pSrcAboveLeft == NULL, OMX_Sts_BadArgErr); |
| armRetArgErrIf(predMode==OMX_VC_4X4_VERT && !(availability & OMX_VC_UPPER), OMX_Sts_BadArgErr); |
| armRetArgErrIf(predMode==OMX_VC_4X4_HOR && !(availability & OMX_VC_LEFT), OMX_Sts_BadArgErr); |
| armRetArgErrIf(predMode==OMX_VC_4X4_DIAG_DL && !(availability & OMX_VC_UPPER), OMX_Sts_BadArgErr); |
| armRetArgErrIf(predMode==OMX_VC_4X4_DIAG_DR && !(availability & OMX_VC_UPPER), OMX_Sts_BadArgErr); |
| armRetArgErrIf(predMode==OMX_VC_4X4_DIAG_DR && !(availability & OMX_VC_UPPER_LEFT), OMX_Sts_BadArgErr); |
| armRetArgErrIf(predMode==OMX_VC_4X4_DIAG_DR && !(availability & OMX_VC_LEFT), OMX_Sts_BadArgErr); |
| armRetArgErrIf(predMode==OMX_VC_4X4_VR && !(availability & OMX_VC_UPPER), OMX_Sts_BadArgErr); |
| armRetArgErrIf(predMode==OMX_VC_4X4_VR && !(availability & OMX_VC_UPPER_LEFT), OMX_Sts_BadArgErr); |
| armRetArgErrIf(predMode==OMX_VC_4X4_VR && !(availability & OMX_VC_LEFT), OMX_Sts_BadArgErr); |
| armRetArgErrIf(predMode==OMX_VC_4X4_HD && !(availability & OMX_VC_UPPER), OMX_Sts_BadArgErr); |
| armRetArgErrIf(predMode==OMX_VC_4X4_HD && !(availability & OMX_VC_UPPER_LEFT), OMX_Sts_BadArgErr); |
| armRetArgErrIf(predMode==OMX_VC_4X4_HD && !(availability & OMX_VC_LEFT), OMX_Sts_BadArgErr); |
| armRetArgErrIf(predMode==OMX_VC_4X4_VL && !(availability & OMX_VC_UPPER), OMX_Sts_BadArgErr); |
| armRetArgErrIf(predMode==OMX_VC_4X4_HU && !(availability & OMX_VC_LEFT), OMX_Sts_BadArgErr); |
| armRetArgErrIf((unsigned)predMode > OMX_VC_4X4_HU, OMX_Sts_BadArgErr); |
| |
| /* Note: This code must not read the pSrc arrays unless the corresponding |
| * block is marked as available. If the block is not avaibable then pSrc |
| * may not be a valid pointer. |
| * |
| * Note: To make the code more readable we refer to the neighbouring pixels |
| * in variables named as below: |
| * |
| * UL U0 U1 U2 U3 U4 U5 U6 U7 |
| * L0 xx xx xx xx |
| * L1 xx xx xx xx |
| * L2 xx xx xx xx |
| * L3 xx xx xx xx |
| */ |
| |
| #define UL pSrcAboveLeft[0] |
| #define U0 pSrcAbove[0] |
| #define U1 pSrcAbove[1] |
| #define U2 pSrcAbove[2] |
| #define U3 pSrcAbove[3] |
| #define U4 pSrcAbove[4] |
| #define U5 pSrcAbove[5] |
| #define U6 pSrcAbove[6] |
| #define U7 pSrcAbove[7] |
| #define L0 pSrcLeft[0*leftStep] |
| #define L1 pSrcLeft[1*leftStep] |
| #define L2 pSrcLeft[2*leftStep] |
| #define L3 pSrcLeft[3*leftStep] |
| |
| switch (predMode) |
| { |
| case OMX_VC_4X4_VERT: |
| for (y=0; y<4; y++) |
| { |
| pDst[y*dstStep+0] = U0; |
| pDst[y*dstStep+1] = U1; |
| pDst[y*dstStep+2] = U2; |
| pDst[y*dstStep+3] = U3; |
| } |
| break; |
| |
| case OMX_VC_4X4_HOR: |
| for (x=0; x<4; x++) |
| { |
| pDst[0*dstStep+x] = L0; |
| pDst[1*dstStep+x] = L1; |
| pDst[2*dstStep+x] = L2; |
| pDst[3*dstStep+x] = L3; |
| } |
| break; |
| |
| case OMX_VC_4X4_DC: |
| /* This can always be used even if no blocks available */ |
| armVCM4P10_PredictIntraDC4x4(pSrcLeft, pSrcAbove, pDst, leftStep, dstStep, availability); |
| break; |
| |
| case OMX_VC_4X4_DIAG_DL: |
| pTmp[0] = (OMX_U8)((U0 + 2*U1 + U2 + 2)>>2); |
| pTmp[1] = (OMX_U8)((U1 + 2*U2 + U3 + 2)>>2); |
| if (availability & OMX_VC_UPPER_RIGHT) |
| { |
| pTmp[2] = (OMX_U8)((U2 + 2*U3 + U4 + 2)>>2); |
| pTmp[3] = (OMX_U8)((U3 + 2*U4 + U5 + 2)>>2); |
| pTmp[4] = (OMX_U8)((U4 + 2*U5 + U6 + 2)>>2); |
| pTmp[5] = (OMX_U8)((U5 + 2*U6 + U7 + 2)>>2); |
| pTmp[6] = (OMX_U8)((U6 + 3*U7 + 2)>>2); |
| } |
| else |
| { |
| pTmp[2] = (OMX_U8)((U2 + 3*U3 + 2)>>2); |
| pTmp[3] = U3; |
| pTmp[4] = U3; |
| pTmp[5] = U3; |
| pTmp[6] = U3; |
| } |
| for (y=0; y<4; y++) |
| { |
| for (x=0; x<4; x++) |
| { |
| pDst[y*dstStep+x] = pTmp[x+y]; |
| } |
| } |
| break; |
| |
| case OMX_VC_4X4_DIAG_DR: |
| /* x-y = -3, -2, -1, 0, 1, 2, 3 */ |
| pTmp[0] = (OMX_U8)((L1 + 2*L2 + L3 + 2)>>2); |
| pTmp[1] = (OMX_U8)((L0 + 2*L1 + L2 + 2)>>2); |
| pTmp[2] = (OMX_U8)((UL + 2*L0 + L1 + 2)>>2); |
| pTmp[3] = (OMX_U8)((U0 + 2*UL + L0 + 2)>>2); |
| pTmp[4] = (OMX_U8)((U1 + 2*U0 + UL + 2)>>2); |
| pTmp[5] = (OMX_U8)((U2 + 2*U1 + U0 + 2)>>2); |
| pTmp[6] = (OMX_U8)((U3 + 2*U2 + U1 + 2)>>2); |
| for (y=0; y<4; y++) |
| { |
| for (x=0; x<4; x++) |
| { |
| pDst[y*dstStep+x] = pTmp[3+x-y]; |
| } |
| } |
| break; |
| |
| case OMX_VC_4X4_VR: |
| /* zVR=2x-y = -3, -2, -1, 0, 1, 2, 3, 4, 5, 6 |
| * x-(y>>1) = -1, -1, 0, 0, 1, 1, 2, 2, 3, 3 |
| * y = 3, 2, ?, ?, ?, ?, ?, ?, 1, 0 |
| */ |
| pTmp[0] = (OMX_U8)((L2 + 2*L1 + L0 + 2)>>2); |
| pTmp[1] = (OMX_U8)((L1 + 2*L0 + UL + 2)>>2); |
| pTmp[2] = (OMX_U8)((L0 + 2*UL + U0 + 2)>>2); |
| pTmp[3] = (OMX_U8)((UL + U0 + 1)>>1); |
| pTmp[4] = (OMX_U8)((UL + 2*U0 + U1 + 2)>>2); |
| pTmp[5] = (OMX_U8)((U0 + U1 + 1)>>1); |
| pTmp[6] = (OMX_U8)((U0 + 2*U1 + U2 + 2)>>2); |
| pTmp[7] = (OMX_U8)((U1 + U2 + 1)>>1); |
| pTmp[8] = (OMX_U8)((U1 + 2*U2 + U3 + 2)>>2); |
| pTmp[9] = (OMX_U8)((U2 + U3 + 1)>>1); |
| for (y=0; y<4; y++) |
| { |
| for (x=0; x<4; x++) |
| { |
| pDst[y*dstStep+x] = pTmp[3+2*x-y]; |
| } |
| } |
| break; |
| |
| case OMX_VC_4X4_HD: |
| /* zHD=2y-x = -3 -2 -1 0 1 2 3 4 5 6 |
| * y-(x>>1) = -1 -1 0 0 1 1 2 2 3 3 |
| * x = 3 2 1 0 |
| */ |
| pTmp[0] = (OMX_U8)((U2 + 2*U1 + U0 + 2)>>2); |
| pTmp[1] = (OMX_U8)((U1 + 2*U0 + UL + 2)>>2); |
| pTmp[2] = (OMX_U8)((U0 + 2*UL + L0 + 2)>>2); |
| pTmp[3] = (OMX_U8)((UL + L0 + 1)>>1); |
| pTmp[4] = (OMX_U8)((UL + 2*L0 + L1 + 2)>>2); |
| pTmp[5] = (OMX_U8)((L0 + L1 + 1)>>1); |
| pTmp[6] = (OMX_U8)((L0 + 2*L1 + L2 + 2)>>2); |
| pTmp[7] = (OMX_U8)((L1 + L2 + 1)>>1); |
| pTmp[8] = (OMX_U8)((L1 + 2*L2 + L3 + 2)>>2); |
| pTmp[9] = (OMX_U8)((L2 + L3 + 1)>>1); |
| for (y=0; y<4; y++) |
| { |
| for (x=0; x<4; x++) |
| { |
| pDst[y*dstStep+x] = pTmp[3+2*y-x]; |
| } |
| } |
| break; |
| |
| case OMX_VC_4X4_VL: |
| /* Note: x+(y>>1) = (2*x+y)>>1 |
| * 2x+y = 0 1 2 3 4 5 6 7 8 9 |
| */ |
| pTmp[0] = (OMX_U8)((U0 + U1 + 1)>>1); |
| pTmp[1] = (OMX_U8)((U0 + 2*U1 + U2 + 2)>>2); |
| pTmp[2] = (OMX_U8)((U1 + U2 + 1)>>1); |
| pTmp[3] = (OMX_U8)((U1 + 2*U2 + U3 + 2)>>2); |
| pTmp[4] = (OMX_U8)((U2 + U3 + 1)>>1); |
| if (availability & OMX_VC_UPPER_RIGHT) |
| { |
| pTmp[5] = (OMX_U8)((U2 + 2*U3 + U4 + 2)>>2); |
| pTmp[6] = (OMX_U8)((U3 + U4 + 1)>>1); |
| pTmp[7] = (OMX_U8)((U3 + 2*U4 + U5 + 2)>>2); |
| pTmp[8] = (OMX_U8)((U4 + U5 + 1)>>1); |
| pTmp[9] = (OMX_U8)((U4 + 2*U5 + U6 + 2)>>2); |
| } |
| else |
| { |
| pTmp[5] = (OMX_U8)((U2 + 3*U3 + 2)>>2); |
| pTmp[6] = U3; |
| pTmp[7] = U3; |
| pTmp[8] = U3; |
| pTmp[9] = U3; |
| } |
| for (y=0; y<4; y++) |
| { |
| for (x=0; x<4; x++) |
| { |
| pDst[y*dstStep+x] = pTmp[2*x+y]; |
| } |
| } |
| break; |
| |
| case OMX_VC_4X4_HU: |
| /* zHU = x+2*y */ |
| pTmp[0] = (OMX_U8)((L0 + L1 + 1)>>1); |
| pTmp[1] = (OMX_U8)((L0 + 2*L1 + L2 + 2)>>2); |
| pTmp[2] = (OMX_U8)((L1 + L2 + 1)>>1); |
| pTmp[3] = (OMX_U8)((L1 + 2*L2 + L3 + 2)>>2); |
| pTmp[4] = (OMX_U8)((L2 + L3 + 1)>>1); |
| pTmp[5] = (OMX_U8)((L2 + 3*L3 + 2)>>2); |
| pTmp[6] = L3; |
| pTmp[7] = L3; |
| pTmp[8] = L3; |
| pTmp[9] = L3; |
| for (y=0; y<4; y++) |
| { |
| for (x=0; x<4; x++) |
| { |
| pDst[y*dstStep+x] = pTmp[x+2*y]; |
| } |
| } |
| break; |
| } |
| |
| return OMX_Sts_NoErr; |
| } |