OMXResult omxVCM4P10_DeblockLuma_I(
	OMX_U8* pSrcDst, 
	OMX_S32 srcdstStep, 
	const OMX_U8* pAlpha, 
	const OMX_U8* pBeta, 
	const OMX_U8* pThresholds, 
	const OMX_U8 *pBS
)
{
    OMXResult errorCode;
    
    armRetArgErrIf(pSrcDst == NULL,             OMX_Sts_BadArgErr);
    armRetArgErrIf(armNot8ByteAligned(pSrcDst), OMX_Sts_BadArgErr);
    armRetArgErrIf(srcdstStep & 7,              OMX_Sts_BadArgErr);    
    armRetArgErrIf(pAlpha == NULL,              OMX_Sts_BadArgErr);
    armRetArgErrIf(pBeta == NULL,               OMX_Sts_BadArgErr);
    armRetArgErrIf(pThresholds == NULL,         OMX_Sts_BadArgErr);
    armRetArgErrIf(armNot4ByteAligned(pThresholds), OMX_Sts_BadArgErr);
    armRetArgErrIf(pBS == NULL,                     OMX_Sts_BadArgErr);
    armRetArgErrIf(armNot4ByteAligned(pBS),         OMX_Sts_BadArgErr);

    errorCode = omxVCM4P10_FilterDeblockingLuma_VerEdge_I(
        pSrcDst, srcdstStep, pAlpha, pBeta, pThresholds, pBS);

    armRetArgErrIf(errorCode != OMX_Sts_NoErr, errorCode)
    
    errorCode = omxVCM4P10_FilterDeblockingLuma_HorEdge_I(
        pSrcDst, srcdstStep, pAlpha+2, pBeta+2, pThresholds+16, pBS+16);

    return errorCode;
}
/**
 * Function:  omxVCCOMM_ExpandFrame_I   (6.1.3.2.1)
 *
 * Description:
 * This function expands a reconstructed frame in-place.  The unexpanded 
 * source frame should be stored in a plane buffer with sufficient space 
 * pre-allocated for edge expansion, and the input frame should be located in 
 * the plane buffer center.  This function executes the pixel expansion by 
 * replicating source frame edge pixel intensities in the empty pixel 
 * locations (expansion region) between the source frame edge and the plane 
 * buffer edge.  The width/height of the expansion regions on the 
 * horizontal/vertical edges is controlled by the parameter iExpandPels. 
 *
 * Input Arguments:
 *   
 *   pSrcDstPlane - pointer to the top-left corner of the frame to be 
 *            expanded; must be aligned on an 8-byte boundary. 
 *   iFrameWidth - frame width; must be a multiple of 8. 
 *   iFrameHeight -frame height; must be a multiple of 8. 
 *   iExpandPels - number of pixels to be expanded in the horizontal and 
 *            vertical directions; must be a multiple of 8. 
 *   iPlaneStep - distance, in bytes, between the start of consecutive lines 
 *            in the plane buffer; must be larger than or equal to 
 *            (iFrameWidth + 2 * iExpandPels). 
 *
 * Output Arguments:
 *   
 *   pSrcDstPlane -Pointer to the top-left corner of the frame (NOT the 
 *            top-left corner of the plane); must be aligned on an 8-byte 
 *            boundary. 
 *
 * Return Value:
 *    
 *    OMX_Sts_NoErr - no error 
 *    OMX_Sts_BadArgErr - bad arguments; returned under any of the following 
 *              conditions: 
 *    -    pSrcDstPlane is NULL. 
 *    -    pSrcDstPlane is not aligned on an 8-byte boundary. 
 *    -    one of the following parameters is either equal to zero or is a 
 *              non-multiple of 8: iFrameHeight, iFrameWidth, iPlaneStep, or 
 *              iExpandPels. 
 *    -    iPlaneStep < (iFrameWidth + 2 * iExpandPels). 
 *
 */
OMXResult omxVCCOMM_ExpandFrame_I(
	OMX_U8*	pSrcDstPlane, 
	OMX_U32	iFrameWidth, 
	OMX_U32	iFrameHeight, 
	OMX_U32	iExpandPels, 
	OMX_U32	iPlaneStep
)
{
    OMX_INT     x, y;
    OMX_U8*     pLeft;
    OMX_U8*     pRight;
    OMX_U8*     pTop;
    OMX_U8*     pBottom;

    /* check for argument error */
    armRetArgErrIf(pSrcDstPlane == NULL, OMX_Sts_BadArgErr)
    armRetArgErrIf(armNot8ByteAligned(pSrcDstPlane), OMX_Sts_BadArgErr)
    armRetArgErrIf(iFrameWidth == 0 || iFrameWidth & 7, OMX_Sts_BadArgErr)
    armRetArgErrIf(iFrameHeight== 0 || iFrameHeight & 7, OMX_Sts_BadArgErr)
    armRetArgErrIf(iExpandPels == 0 || iExpandPels & 7, OMX_Sts_BadArgErr)
    armRetArgErrIf(iPlaneStep == 0 || iPlaneStep & 7, OMX_Sts_BadArgErr)
    armRetArgErrIf(iPlaneStep < (iFrameWidth + 2 * iExpandPels), 
                   OMX_Sts_BadArgErr)

    /* Top and Bottom */
    pTop = pSrcDstPlane - (iExpandPels * iPlaneStep);
    pBottom = pSrcDstPlane + (iFrameHeight * iPlaneStep);

    for (y = 0; y < (OMX_INT)iExpandPels; y++)
    {
        for (x = 0; x < (OMX_INT)iFrameWidth; x++)
        {
            pTop [y * iPlaneStep + x] = 
                pSrcDstPlane [x];
            pBottom [y * iPlaneStep + x] = 
                pSrcDstPlane [(iFrameHeight - 1) * iPlaneStep + x];
        }
    }

    /* Left, Right and Corners */
    pLeft = pSrcDstPlane - iExpandPels;
    pRight = pSrcDstPlane + iFrameWidth;

    for (y = -(OMX_INT)iExpandPels; y < (OMX_INT)(iFrameHeight + iExpandPels); y++)
    {
        for (x = 0; x < (OMX_INT)iExpandPels; x++)
        {
            pLeft [y * iPlaneStep + x] = 
                pSrcDstPlane [y * iPlaneStep + 0];
            pRight [y * iPlaneStep + x] = 
                pSrcDstPlane [y * iPlaneStep + (iFrameWidth - 1)];
        }
    }

    return OMX_Sts_NoErr;
}
OMXResult omxVCM4P10_TransformDequantLumaDCFromPair(
     const OMX_U8 **ppSrc,
     OMX_S16* pDst,
     OMX_INT QP        
 )
{
    armRetArgErrIf(ppSrc  == NULL,           OMX_Sts_BadArgErr);
    armRetArgErrIf(*ppSrc == NULL,           OMX_Sts_BadArgErr);
    armRetArgErrIf(pDst   == NULL,           OMX_Sts_BadArgErr);
    armRetArgErrIf(armNot8ByteAligned(pDst), OMX_Sts_BadArgErr);
    armRetArgErrIf(QP<0,                     OMX_Sts_BadArgErr);
    armRetArgErrIf(QP>51,                    OMX_Sts_BadArgErr);

    armVCM4P10_UnpackBlock4x4(ppSrc, pDst);
    /*InvTransformDequantLumaDC4x4(pDst, QP);*/
    InvTransformDC4x4(pDst);
    DequantLumaDC4x4(pDst, QP);

    return OMX_Sts_NoErr;
}
/**
 * Function:  omxVCM4P10_GetVLCInfo   (6.3.5.9.1)
 *
 * Description:
 * This function extracts run-length encoding (RLE) information from the 
 * coefficient matrix.  The results are returned in an OMXVCM4P10VLCInfo 
 * structure. 
 *
 * Input Arguments:
 *   
 *   pSrcCoeff - pointer to the transform coefficient matrix.  8-byte 
 *            alignment required. 
 *   pScanMatrix - pointer to the scan order definition matrix.  For a luma 
 *            block the scan matrix should follow [ISO14496-10] section 8.5.4, 
 *            and should contain the values 0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 
 *            10, 7, 11, 14, 15.  For a chroma block, the scan matrix should 
 *            contain the values 0, 1, 2, 3. 
 *   bAC - indicates presence of a DC coefficient; 0 = DC coefficient 
 *            present, 1= DC coefficient absent. 
 *   MaxNumCoef - specifies the number of coefficients contained in the 
 *            transform coefficient matrix, pSrcCoeff. The value should be 16 
 *            for blocks of type LUMADC, LUMAAC, LUMALEVEL, and CHROMAAC. The 
 *            value should be 4 for blocks of type CHROMADC. 
 *
 * Output Arguments:
 *   
 *   pDstVLCInfo - pointer to structure that stores information for 
 *            run-length coding. 
 *
 * Return Value:
 *    
 *    OMX_Sts_NoErr - no error 
 *    OMX_Sts_BadArgErr - bad arguments; returned if any of the following 
 *              conditions are true: 
 *    -    at least one of the following pointers is NULL: 
 *            pSrcCoeff, pScanMatrix, pDstVLCInfo 
 *    -    pSrcCoeff is not aligned on an 8-byte boundary 
 *
 */
OMXResult omxVCM4P10_GetVLCInfo (
	const OMX_S16*		    pSrcCoeff,
	const OMX_U8*			    pScanMatrix,
	OMX_U8			    bAC,
	OMX_U32			    MaxNumCoef,
	OMXVCM4P10VLCInfo*	pDstVLCInfo
)
{
    OMX_INT     i, MinIndex;
    OMX_S32     Value;
    OMX_U32     Mask = 4, RunBefore;
    OMX_S16     *pLevel;
    OMX_U8      *pRun;
    OMX_S16     Buf [16];

    /* check for argument error */
    armRetArgErrIf(pSrcCoeff == NULL, OMX_Sts_BadArgErr)
    armRetArgErrIf(armNot8ByteAligned(pSrcCoeff), OMX_Sts_BadArgErr)
    armRetArgErrIf(pScanMatrix == NULL, OMX_Sts_BadArgErr)
    armRetArgErrIf(pDstVLCInfo == NULL, OMX_Sts_BadArgErr)
    armRetArgErrIf(bAC > 1, OMX_Sts_BadArgErr)
    armRetArgErrIf(MaxNumCoef > 16, OMX_Sts_BadArgErr)

    /* Initialize RLE Info structure */
    pDstVLCInfo->uTrailing_Ones = 0;
    pDstVLCInfo->uTrailing_One_Signs = 0;
    pDstVLCInfo->uNumCoeffs = 0;
    pDstVLCInfo->uTotalZeros = 0;

    for (i = 0; i < 16; i++)
    {
        pDstVLCInfo->iLevels [i] = 0;
        pDstVLCInfo->uRuns [i] = 0;
    }
    
    MinIndex = (bAC == 0 && MaxNumCoef == 15) ? 1 : 0;
    for (i = MinIndex; i < (MaxNumCoef + MinIndex); i++)
    {        
        /* Scan */
        Buf [i - MinIndex] = pSrcCoeff [pScanMatrix [i]];
    }

    /* skip zeros at the end */
    i = MaxNumCoef - 1;
    while (!Buf [i] && i >= 0)
    {
        i--;
    }
    
    if (i < 0)
    {
        return OMX_Sts_NoErr;
    }

    /* Fill RLE Info structure */
    pLevel = pDstVLCInfo->iLevels;
    pRun = pDstVLCInfo->uRuns;
    RunBefore = 0;

    /* Handle first non zero separate */
    pDstVLCInfo->uNumCoeffs++;
    Value = Buf [i];
    if (Value == 1 || Value == -1)
    {
        pDstVLCInfo->uTrailing_Ones++;
        
        pDstVLCInfo->uTrailing_One_Signs |= 
            Value == -1 ? Mask : 0;
        Mask >>= 1;
    }
/**
 * Function:  omxVCM4P10_PredictIntraChroma_8x8   (6.3.3.1.3)
 *
 * Description:
 * Performs intra prediction for chroma samples. 
 *
 * Input Arguments:
 *   
 *   pSrcLeft - Pointer to the buffer of 8 left pixels: p[x, y] (x = -1, y= 
 *            0..7). 
 *   pSrcAbove - Pointer to the buffer of 8 above pixels: p[x,y] (x = 0..7, y 
 *            = -1); must be aligned on an 8-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 8. 
 *   dstStep - Step of the destination buffer; must be a multiple of 8. 
 *   predMode - Intra chroma prediction mode, please refer to section 3.4.3. 
 *   availability - Neighboring chroma block availability flag, please refer 
 *            to  "Neighboring Macroblock Availability". 
 *
 * Output Arguments:
 *   
 *   pDst - Pointer to the destination buffer; must be aligned on an 8-byte 
 *            boundary. 
 *
 * Return Value:
 *    If the function runs without error, it returns OMX_Sts_NoErr. 
 *    If any of the following cases occurs, the function returns 
 *              OMX_Sts_BadArgErr: 
 *    pDst is NULL. 
 *    dstStep < 8 or dstStep is not a multiple of 8. 
 *    leftStep is not a multiple of 8. 
 *    predMode is not in the valid range of enumeration 
 *              OMXVCM4P10IntraChromaPredMode. 
 *    predMode is OMX_VC_CHROMA_VERT, but availability doesn't set 
 *              OMX_VC_UPPER indicating p[x,-1] (x = 0..7) is not available. 
 *    predMode is OMX_VC_CHROMA_HOR, but availability doesn't set OMX_VC_LEFT 
 *              indicating p[-1,y] (y = 0..7) is not available. 
 *    predMode is OMX_VC_CHROMA_PLANE, but availability doesn't set 
 *              OMX_VC_UPPER_LEFT or OMX_VC_UPPER or OMX_VC_LEFT indicating 
 *              p[x,-1](x = 0..7), or p[-1,y] (y = 0..7), or p[-1,-1] 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 8-byte boundary.  Note: 
 *              pSrcAbove, pSrcAbove, pSrcAboveLeft may be invalid pointer if 
 *              they are not used by intra prediction implied in predMode. 
 *               Note: OMX_VC_UPPER_RIGHT is not used in intra chroma 
 *              prediction. 
 *
 */
OMXResult omxVCM4P10_PredictIntraChroma_8x8(
     const OMX_U8* pSrcLeft,
     const OMX_U8 *pSrcAbove,
     const OMX_U8 *pSrcAboveLeft,
     OMX_U8* pDst,
     OMX_INT leftStep,
     OMX_INT dstStep,
     OMXVCM4P10IntraChromaPredMode predMode,
     OMX_S32 availability        
 )
{
    int x, y, Sum;
    int H, V, a, b, c;

    armRetArgErrIf(pDst == NULL, OMX_Sts_BadArgErr);
    armRetArgErrIf(dstStep < 8,  OMX_Sts_BadArgErr);
    armRetArgErrIf((dstStep % 8) != 0,  OMX_Sts_BadArgErr);
    armRetArgErrIf((leftStep % 8) != 0,  OMX_Sts_BadArgErr);
    armRetArgErrIf(armNot8ByteAligned(pSrcAbove), OMX_Sts_BadArgErr);
    armRetArgErrIf(armNot8ByteAligned(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_CHROMA_VERT  && !(availability & OMX_VC_UPPER),      OMX_Sts_BadArgErr);
    armRetArgErrIf(predMode==OMX_VC_CHROMA_HOR   && !(availability & OMX_VC_LEFT),       OMX_Sts_BadArgErr);
    armRetArgErrIf(predMode==OMX_VC_CHROMA_PLANE && !(availability & OMX_VC_UPPER),      OMX_Sts_BadArgErr);
    armRetArgErrIf(predMode==OMX_VC_CHROMA_PLANE && !(availability & OMX_VC_UPPER_LEFT), OMX_Sts_BadArgErr);
    armRetArgErrIf(predMode==OMX_VC_CHROMA_PLANE && !(availability & OMX_VC_LEFT),       OMX_Sts_BadArgErr);
    armRetArgErrIf((unsigned)predMode > OMX_VC_CHROMA_PLANE,   OMX_Sts_BadArgErr);    

    switch (predMode)
    {
    case OMX_VC_CHROMA_DC:
        armVCM4P10_PredictIntraDC4x4(       pSrcLeft,            pSrcAbove,   pDst,             leftStep, dstStep, availability);
        armVCM4P10_PredictIntraDCUp4x4(     pSrcLeft,            pSrcAbove+4, pDst+4,           leftStep, dstStep, availability);
        armVCM4P10_PredictIntraDCLeft4x4(   pSrcLeft+4*leftStep, pSrcAbove,   pDst+4*dstStep,   leftStep, dstStep, availability);
        armVCM4P10_PredictIntraDC4x4(       pSrcLeft+4*leftStep, pSrcAbove+4, pDst+4+4*dstStep, leftStep, dstStep, availability);
        break;

    case OMX_VC_CHROMA_HOR:
        for (y=0; y<8; y++)
        {
            for (x=0; x<8; x++)
            {
                pDst[y*dstStep+x] = pSrcLeft[y*leftStep];
            }
        }
        break;

    case OMX_VC_CHROMA_VERT:
        for (y=0; y<8; y++)
        {
            for (x=0; x<8; x++)
            {
                pDst[y*dstStep+x] = pSrcAbove[x];
            }
        }
        break;

    case OMX_VC_CHROMA_PLANE:
        H = 4*(pSrcAbove[7] - pSrcAboveLeft[0]);
        for (x=2; x>=0; x--)
        {
            H += (x+1)*(pSrcAbove[4+x] - pSrcAbove[2-x]);
        }
        V = 4*(pSrcLeft[7*leftStep] - pSrcAboveLeft[0]);
        for (y=2; y>=0; y--)
        {
            V += (y+1)*(pSrcLeft[(4+y)*leftStep] - pSrcLeft[(2-y)*leftStep]);
        }
        a = 16*(pSrcAbove[7] + pSrcLeft[7*leftStep]);
        b = (17*H+16)>>5;
        c = (17*V+16)>>5;
        for (y=0; y<8; y++)
        {
            for (x=0; x<8; x++)
            {
                Sum = (a + b*(x-3) + c*(y-3) + 16)>>5;
                pDst[y*dstStep+x] = (OMX_U8)armClip(0,255,Sum);
            }
        }
        break;
    }

    return OMX_Sts_NoErr;
}