Home | History | Annotate | Download | only in src
      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