178e52bfac041d71ce53b5b13c2abf78af742b09dLajos Molnar/*
278e52bfac041d71ce53b5b13c2abf78af742b09dLajos Molnar * Copyright (C) 2007-2008 ARM Limited
378e52bfac041d71ce53b5b13c2abf78af742b09dLajos Molnar *
478e52bfac041d71ce53b5b13c2abf78af742b09dLajos Molnar * Licensed under the Apache License, Version 2.0 (the "License");
578e52bfac041d71ce53b5b13c2abf78af742b09dLajos Molnar * you may not use this file except in compliance with the License.
678e52bfac041d71ce53b5b13c2abf78af742b09dLajos Molnar * You may obtain a copy of the License at
778e52bfac041d71ce53b5b13c2abf78af742b09dLajos Molnar *
878e52bfac041d71ce53b5b13c2abf78af742b09dLajos Molnar *      http://www.apache.org/licenses/LICENSE-2.0
978e52bfac041d71ce53b5b13c2abf78af742b09dLajos Molnar *
1078e52bfac041d71ce53b5b13c2abf78af742b09dLajos Molnar * Unless required by applicable law or agreed to in writing, software
1178e52bfac041d71ce53b5b13c2abf78af742b09dLajos Molnar * distributed under the License is distributed on an "AS IS" BASIS,
1278e52bfac041d71ce53b5b13c2abf78af742b09dLajos Molnar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1378e52bfac041d71ce53b5b13c2abf78af742b09dLajos Molnar * See the License for the specific language governing permissions and
1478e52bfac041d71ce53b5b13c2abf78af742b09dLajos Molnar * limitations under the License.
1578e52bfac041d71ce53b5b13c2abf78af742b09dLajos Molnar *
1678e52bfac041d71ce53b5b13c2abf78af742b09dLajos Molnar */
170c1bc742181ded4930842b46e9507372f0b1b963James Dong/**
180c1bc742181ded4930842b46e9507372f0b1b963James Dong *
190c1bc742181ded4930842b46e9507372f0b1b963James Dong * File Name:  omxVCM4P10_SubAndTransformQDQResidual.c
200c1bc742181ded4930842b46e9507372f0b1b963James Dong * OpenMAX DL: v1.0.2
210c1bc742181ded4930842b46e9507372f0b1b963James Dong * Revision:   9641
220c1bc742181ded4930842b46e9507372f0b1b963James Dong * Date:       Thursday, February 7, 2008
230c1bc742181ded4930842b46e9507372f0b1b963James Dong *
240c1bc742181ded4930842b46e9507372f0b1b963James Dong *
250c1bc742181ded4930842b46e9507372f0b1b963James Dong *
260c1bc742181ded4930842b46e9507372f0b1b963James Dong * Description:
270c1bc742181ded4930842b46e9507372f0b1b963James Dong * This function will calculate SAD for 4x4 blocks
280c1bc742181ded4930842b46e9507372f0b1b963James Dong *
290c1bc742181ded4930842b46e9507372f0b1b963James Dong */
300c1bc742181ded4930842b46e9507372f0b1b963James Dong
310c1bc742181ded4930842b46e9507372f0b1b963James Dong#include "omxtypes.h"
320c1bc742181ded4930842b46e9507372f0b1b963James Dong#include "armOMX.h"
330c1bc742181ded4930842b46e9507372f0b1b963James Dong#include "omxVC.h"
340c1bc742181ded4930842b46e9507372f0b1b963James Dong
350c1bc742181ded4930842b46e9507372f0b1b963James Dong#include "armCOMM.h"
360c1bc742181ded4930842b46e9507372f0b1b963James Dong#include "armVC.h"
370c1bc742181ded4930842b46e9507372f0b1b963James Dong
380c1bc742181ded4930842b46e9507372f0b1b963James Dong/**
390c1bc742181ded4930842b46e9507372f0b1b963James Dong * Function:  omxVCM4P10_SubAndTransformQDQResidual   (6.3.5.8.1)
400c1bc742181ded4930842b46e9507372f0b1b963James Dong *
410c1bc742181ded4930842b46e9507372f0b1b963James Dong * Description:
420c1bc742181ded4930842b46e9507372f0b1b963James Dong * This function subtracts the prediction signal from the original signal to
430c1bc742181ded4930842b46e9507372f0b1b963James Dong * produce the difference signal and then performs a 4x4 integer transform and
440c1bc742181ded4930842b46e9507372f0b1b963James Dong * quantization. The quantized transformed coefficients are stored as
450c1bc742181ded4930842b46e9507372f0b1b963James Dong * pDstQuantCoeff. This function can also output dequantized coefficients or
460c1bc742181ded4930842b46e9507372f0b1b963James Dong * unquantized DC coefficients optionally by setting the pointers
470c1bc742181ded4930842b46e9507372f0b1b963James Dong * pDstDeQuantCoeff, pDCCoeff.
480c1bc742181ded4930842b46e9507372f0b1b963James Dong *
490c1bc742181ded4930842b46e9507372f0b1b963James Dong * Input Arguments:
500c1bc742181ded4930842b46e9507372f0b1b963James Dong *
510c1bc742181ded4930842b46e9507372f0b1b963James Dong *   pSrcOrg - Pointer to original signal. 4-byte alignment required.
520c1bc742181ded4930842b46e9507372f0b1b963James Dong *   pSrcPred - Pointer to prediction signal. 4-byte alignment required.
530c1bc742181ded4930842b46e9507372f0b1b963James Dong *   iSrcOrgStep - Step of the original signal buffer; must be a multiple of
540c1bc742181ded4930842b46e9507372f0b1b963James Dong *            4.
550c1bc742181ded4930842b46e9507372f0b1b963James Dong *   iSrcPredStep - Step of the prediction signal buffer; must be a multiple
560c1bc742181ded4930842b46e9507372f0b1b963James Dong *            of 4.
570c1bc742181ded4930842b46e9507372f0b1b963James Dong *   pNumCoeff -Number of non-zero coefficients after quantization. If this
580c1bc742181ded4930842b46e9507372f0b1b963James Dong *            parameter is not required, it is set to NULL.
590c1bc742181ded4930842b46e9507372f0b1b963James Dong *   nThreshSAD - Zero-block early detection threshold. If this parameter is
600c1bc742181ded4930842b46e9507372f0b1b963James Dong *            not required, it is set to 0.
610c1bc742181ded4930842b46e9507372f0b1b963James Dong *   iQP - Quantization parameter; must be in the range [0,51].
620c1bc742181ded4930842b46e9507372f0b1b963James Dong *   bIntra - Indicates whether this is an INTRA block, either 1-INTRA or
630c1bc742181ded4930842b46e9507372f0b1b963James Dong *            0-INTER
640c1bc742181ded4930842b46e9507372f0b1b963James Dong *
650c1bc742181ded4930842b46e9507372f0b1b963James Dong * Output Arguments:
660c1bc742181ded4930842b46e9507372f0b1b963James Dong *
670c1bc742181ded4930842b46e9507372f0b1b963James Dong *   pDstQuantCoeff - Pointer to the quantized transformed coefficients.
680c1bc742181ded4930842b46e9507372f0b1b963James Dong *            8-byte alignment required.
690c1bc742181ded4930842b46e9507372f0b1b963James Dong *   pDstDeQuantCoeff - Pointer to the dequantized transformed coefficients
700c1bc742181ded4930842b46e9507372f0b1b963James Dong *            if this parameter is not equal to NULL.  8-byte alignment
710c1bc742181ded4930842b46e9507372f0b1b963James Dong *            required.
720c1bc742181ded4930842b46e9507372f0b1b963James Dong *   pDCCoeff - Pointer to the unquantized DC coefficient if this parameter
730c1bc742181ded4930842b46e9507372f0b1b963James Dong *            is not equal to NULL.
740c1bc742181ded4930842b46e9507372f0b1b963James Dong *
750c1bc742181ded4930842b46e9507372f0b1b963James Dong * Return Value:
760c1bc742181ded4930842b46e9507372f0b1b963James Dong *
770c1bc742181ded4930842b46e9507372f0b1b963James Dong *    OMX_Sts_NoErr - no error
780c1bc742181ded4930842b46e9507372f0b1b963James Dong *    OMX_Sts_BadArgErr - bad arguments; returned if any of the following
790c1bc742181ded4930842b46e9507372f0b1b963James Dong *              conditions are true:
800c1bc742181ded4930842b46e9507372f0b1b963James Dong *    -    at least one of the following pointers is NULL:
810c1bc742181ded4930842b46e9507372f0b1b963James Dong *            pSrcOrg, pSrcPred, pNumCoeff, pDstQuantCoeff,
820c1bc742181ded4930842b46e9507372f0b1b963James Dong *            pDstDeQuantCoeff, pDCCoeff
830c1bc742181ded4930842b46e9507372f0b1b963James Dong *    -    pSrcOrg is not aligned on a 4-byte boundary
840c1bc742181ded4930842b46e9507372f0b1b963James Dong *    -    pSrcPred is not aligned on a 4-byte boundary
850c1bc742181ded4930842b46e9507372f0b1b963James Dong *    -    iSrcOrgStep is not a multiple of 4
860c1bc742181ded4930842b46e9507372f0b1b963James Dong *    -    iSrcPredStep is not a multiple of 4
870c1bc742181ded4930842b46e9507372f0b1b963James Dong *    -    pDstQuantCoeff or pDstDeQuantCoeff is not aligned on an 8-byte boundary
880c1bc742181ded4930842b46e9507372f0b1b963James Dong *
890c1bc742181ded4930842b46e9507372f0b1b963James Dong */
900c1bc742181ded4930842b46e9507372f0b1b963James Dong OMXResult omxVCM4P10_SubAndTransformQDQResidual (
910c1bc742181ded4930842b46e9507372f0b1b963James Dong	 const OMX_U8*		pSrcOrg,
920c1bc742181ded4930842b46e9507372f0b1b963James Dong	 const OMX_U8*		pSrcPred,
930c1bc742181ded4930842b46e9507372f0b1b963James Dong	 OMX_U32		iSrcOrgStep,
940c1bc742181ded4930842b46e9507372f0b1b963James Dong	 OMX_U32		iSrcPredStep,
950c1bc742181ded4930842b46e9507372f0b1b963James Dong	 OMX_S16*	    pDstQuantCoeff,
960c1bc742181ded4930842b46e9507372f0b1b963James Dong	 OMX_S16* 	    pDstDeQuantCoeff,
970c1bc742181ded4930842b46e9507372f0b1b963James Dong	 OMX_S16*	    pDCCoeff,
980c1bc742181ded4930842b46e9507372f0b1b963James Dong	 OMX_S8*		pNumCoeff,
990c1bc742181ded4930842b46e9507372f0b1b963James Dong	 OMX_U32		nThreshSAD,
1000c1bc742181ded4930842b46e9507372f0b1b963James Dong	 OMX_U32		iQP,
1010c1bc742181ded4930842b46e9507372f0b1b963James Dong	 OMX_U8		    bIntra
1020c1bc742181ded4930842b46e9507372f0b1b963James Dong)
1030c1bc742181ded4930842b46e9507372f0b1b963James Dong{
1040c1bc742181ded4930842b46e9507372f0b1b963James Dong    OMX_INT     i, j;
1050c1bc742181ded4930842b46e9507372f0b1b963James Dong    OMX_S8      NumCoeff = 0;
1060c1bc742181ded4930842b46e9507372f0b1b963James Dong    OMX_S16     Buf[16], m[16];
1070c1bc742181ded4930842b46e9507372f0b1b963James Dong    OMX_U32     QBits, QPper, QPmod, f;
1080c1bc742181ded4930842b46e9507372f0b1b963James Dong    OMX_S32     Value, MF, ThreshDC;
1090c1bc742181ded4930842b46e9507372f0b1b963James Dong
1100c1bc742181ded4930842b46e9507372f0b1b963James Dong    /* check for argument error */
1110c1bc742181ded4930842b46e9507372f0b1b963James Dong    armRetArgErrIf(pSrcOrg == NULL, OMX_Sts_BadArgErr)
1120c1bc742181ded4930842b46e9507372f0b1b963James Dong	armRetArgErrIf(pDstDeQuantCoeff == NULL, OMX_Sts_BadArgErr)
1130c1bc742181ded4930842b46e9507372f0b1b963James Dong	armRetArgErrIf(pNumCoeff == NULL, OMX_Sts_BadArgErr)
1140c1bc742181ded4930842b46e9507372f0b1b963James Dong	armRetArgErrIf(pDCCoeff == NULL, OMX_Sts_BadArgErr)
1150c1bc742181ded4930842b46e9507372f0b1b963James Dong    armRetArgErrIf(armNot4ByteAligned(pSrcOrg), OMX_Sts_BadArgErr)
1160c1bc742181ded4930842b46e9507372f0b1b963James Dong    armRetArgErrIf(pSrcPred == NULL, OMX_Sts_BadArgErr)
1170c1bc742181ded4930842b46e9507372f0b1b963James Dong    armRetArgErrIf(armNot4ByteAligned(pSrcPred), OMX_Sts_BadArgErr)
1180c1bc742181ded4930842b46e9507372f0b1b963James Dong    armRetArgErrIf(pDstQuantCoeff == NULL, OMX_Sts_BadArgErr)
1190c1bc742181ded4930842b46e9507372f0b1b963James Dong    armRetArgErrIf(armNot8ByteAligned(pDstQuantCoeff), OMX_Sts_BadArgErr)
1200c1bc742181ded4930842b46e9507372f0b1b963James Dong    armRetArgErrIf((pDstDeQuantCoeff != NULL) &&
1210c1bc742181ded4930842b46e9507372f0b1b963James Dong			armNot8ByteAligned(pDstDeQuantCoeff), OMX_Sts_BadArgErr)
1220c1bc742181ded4930842b46e9507372f0b1b963James Dong    armRetArgErrIf((bIntra != 0) && (bIntra != 1), OMX_Sts_BadArgErr)
1230c1bc742181ded4930842b46e9507372f0b1b963James Dong    armRetArgErrIf(iQP > 51, OMX_Sts_BadArgErr)
1240c1bc742181ded4930842b46e9507372f0b1b963James Dong    armRetArgErrIf(iSrcOrgStep == 0, OMX_Sts_BadArgErr)
1250c1bc742181ded4930842b46e9507372f0b1b963James Dong    armRetArgErrIf(iSrcPredStep == 0, OMX_Sts_BadArgErr)
1260c1bc742181ded4930842b46e9507372f0b1b963James Dong    armRetArgErrIf(iSrcOrgStep & 3, OMX_Sts_BadArgErr)
1270c1bc742181ded4930842b46e9507372f0b1b963James Dong    armRetArgErrIf(iSrcPredStep & 3, OMX_Sts_BadArgErr)
1280c1bc742181ded4930842b46e9507372f0b1b963James Dong
1290c1bc742181ded4930842b46e9507372f0b1b963James Dong    /*
1300c1bc742181ded4930842b46e9507372f0b1b963James Dong     * Zero-Block Early detection using nThreshSAD param
1310c1bc742181ded4930842b46e9507372f0b1b963James Dong     */
1320c1bc742181ded4930842b46e9507372f0b1b963James Dong
1330c1bc742181ded4930842b46e9507372f0b1b963James Dong    QPper = iQP / 6;
1340c1bc742181ded4930842b46e9507372f0b1b963James Dong    QPmod = iQP % 6;
1350c1bc742181ded4930842b46e9507372f0b1b963James Dong    QBits = 15 + QPper;
1360c1bc742181ded4930842b46e9507372f0b1b963James Dong
1370c1bc742181ded4930842b46e9507372f0b1b963James Dong    f = (1 << QBits) / (bIntra ? 3 : 6);
1380c1bc742181ded4930842b46e9507372f0b1b963James Dong
1390c1bc742181ded4930842b46e9507372f0b1b963James Dong    /* Do Zero-Block Early detection if enabled */
1400c1bc742181ded4930842b46e9507372f0b1b963James Dong    if (nThreshSAD)
1410c1bc742181ded4930842b46e9507372f0b1b963James Dong    {
1420c1bc742181ded4930842b46e9507372f0b1b963James Dong        ThreshDC = ((1 << QBits) - f) / armVCM4P10_MFMatrix[QPmod][0];
1430c1bc742181ded4930842b46e9507372f0b1b963James Dong        if (nThreshSAD < ThreshDC)
1440c1bc742181ded4930842b46e9507372f0b1b963James Dong        {
1450c1bc742181ded4930842b46e9507372f0b1b963James Dong            /* Set block to zero */
1460c1bc742181ded4930842b46e9507372f0b1b963James Dong            if (pDCCoeff != NULL)
1470c1bc742181ded4930842b46e9507372f0b1b963James Dong            {
1480c1bc742181ded4930842b46e9507372f0b1b963James Dong                *pDCCoeff = 0;
1490c1bc742181ded4930842b46e9507372f0b1b963James Dong            }
1500c1bc742181ded4930842b46e9507372f0b1b963James Dong
1510c1bc742181ded4930842b46e9507372f0b1b963James Dong            for (j = 0; j < 4; j++)
1520c1bc742181ded4930842b46e9507372f0b1b963James Dong            {
1530c1bc742181ded4930842b46e9507372f0b1b963James Dong                for (i = 0; i < 4; i++)
1540c1bc742181ded4930842b46e9507372f0b1b963James Dong                {
1550c1bc742181ded4930842b46e9507372f0b1b963James Dong                    pDstQuantCoeff [4 * j + i] = 0;
1560c1bc742181ded4930842b46e9507372f0b1b963James Dong                    if (pDstDeQuantCoeff != NULL)
1570c1bc742181ded4930842b46e9507372f0b1b963James Dong                    {
1580c1bc742181ded4930842b46e9507372f0b1b963James Dong                        pDstDeQuantCoeff [4 * j + i] = 0;
1590c1bc742181ded4930842b46e9507372f0b1b963James Dong                    }
1600c1bc742181ded4930842b46e9507372f0b1b963James Dong                }
1610c1bc742181ded4930842b46e9507372f0b1b963James Dong            }
1620c1bc742181ded4930842b46e9507372f0b1b963James Dong
1630c1bc742181ded4930842b46e9507372f0b1b963James Dong            if (pNumCoeff != NULL)
1640c1bc742181ded4930842b46e9507372f0b1b963James Dong            {
1650c1bc742181ded4930842b46e9507372f0b1b963James Dong                *pNumCoeff = 0;
1660c1bc742181ded4930842b46e9507372f0b1b963James Dong            }
1670c1bc742181ded4930842b46e9507372f0b1b963James Dong            return OMX_Sts_NoErr;
1680c1bc742181ded4930842b46e9507372f0b1b963James Dong        }
1690c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
1700c1bc742181ded4930842b46e9507372f0b1b963James Dong
1710c1bc742181ded4930842b46e9507372f0b1b963James Dong
1720c1bc742181ded4930842b46e9507372f0b1b963James Dong   /* Calculate difference */
1730c1bc742181ded4930842b46e9507372f0b1b963James Dong    for (j = 0; j < 4; j++)
1740c1bc742181ded4930842b46e9507372f0b1b963James Dong    {
1750c1bc742181ded4930842b46e9507372f0b1b963James Dong        for (i = 0; i < 4; i++)
1760c1bc742181ded4930842b46e9507372f0b1b963James Dong        {
1770c1bc742181ded4930842b46e9507372f0b1b963James Dong            Buf [j * 4 + i] =
1780c1bc742181ded4930842b46e9507372f0b1b963James Dong                pSrcOrg [j * iSrcOrgStep + i] - pSrcPred [j * iSrcPredStep + i];
1790c1bc742181ded4930842b46e9507372f0b1b963James Dong        }
1800c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
1810c1bc742181ded4930842b46e9507372f0b1b963James Dong
1820c1bc742181ded4930842b46e9507372f0b1b963James Dong    /* Residual Transform */
1830c1bc742181ded4930842b46e9507372f0b1b963James Dong    armVCM4P10_FwdTransformResidual4x4 (m, Buf);
1840c1bc742181ded4930842b46e9507372f0b1b963James Dong
1850c1bc742181ded4930842b46e9507372f0b1b963James Dong    if (pDCCoeff != NULL)
1860c1bc742181ded4930842b46e9507372f0b1b963James Dong    {
1870c1bc742181ded4930842b46e9507372f0b1b963James Dong        /* Copy unquantized DC value into pointer */
1880c1bc742181ded4930842b46e9507372f0b1b963James Dong        *pDCCoeff = m[0];
1890c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
1900c1bc742181ded4930842b46e9507372f0b1b963James Dong
1910c1bc742181ded4930842b46e9507372f0b1b963James Dong    /* Quantization */
1920c1bc742181ded4930842b46e9507372f0b1b963James Dong    for (j = 0; j < 4; j++)
1930c1bc742181ded4930842b46e9507372f0b1b963James Dong    {
1940c1bc742181ded4930842b46e9507372f0b1b963James Dong        for (i = 0; i < 4; i++)
1950c1bc742181ded4930842b46e9507372f0b1b963James Dong        {
1960c1bc742181ded4930842b46e9507372f0b1b963James Dong            MF = armVCM4P10_MFMatrix[QPmod][armVCM4P10_PosToVCol4x4[j * 4 + i]];
1970c1bc742181ded4930842b46e9507372f0b1b963James Dong            Value = armAbs(m[j * 4 + i]) * MF + f;
1980c1bc742181ded4930842b46e9507372f0b1b963James Dong            Value >>= QBits;
1990c1bc742181ded4930842b46e9507372f0b1b963James Dong            Value = m[j * 4 + i] < 0 ? -Value : Value;
2000c1bc742181ded4930842b46e9507372f0b1b963James Dong            Buf[4 * j + i] = pDstQuantCoeff [4 * j + i] = (OMX_S16)Value;
2010c1bc742181ded4930842b46e9507372f0b1b963James Dong            if ((pNumCoeff != NULL) && Value)
2020c1bc742181ded4930842b46e9507372f0b1b963James Dong            {
2030c1bc742181ded4930842b46e9507372f0b1b963James Dong                NumCoeff++;
2040c1bc742181ded4930842b46e9507372f0b1b963James Dong            }
2050c1bc742181ded4930842b46e9507372f0b1b963James Dong        }
2060c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
2070c1bc742181ded4930842b46e9507372f0b1b963James Dong
2080c1bc742181ded4930842b46e9507372f0b1b963James Dong    /* Output number of non-zero Coeffs */
2090c1bc742181ded4930842b46e9507372f0b1b963James Dong    if (pNumCoeff != NULL)
2100c1bc742181ded4930842b46e9507372f0b1b963James Dong    {
2110c1bc742181ded4930842b46e9507372f0b1b963James Dong        *pNumCoeff = NumCoeff;
2120c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
2130c1bc742181ded4930842b46e9507372f0b1b963James Dong
2140c1bc742181ded4930842b46e9507372f0b1b963James Dong    /* Residual Inv Transform */
2150c1bc742181ded4930842b46e9507372f0b1b963James Dong    if (pDstDeQuantCoeff != NULL)
2160c1bc742181ded4930842b46e9507372f0b1b963James Dong    {
2170c1bc742181ded4930842b46e9507372f0b1b963James Dong        /* Re Scale */
2180c1bc742181ded4930842b46e9507372f0b1b963James Dong        for (j = 0; j < 4; j++)
2190c1bc742181ded4930842b46e9507372f0b1b963James Dong        {
2200c1bc742181ded4930842b46e9507372f0b1b963James Dong            for (i = 0; i < 4; i++)
2210c1bc742181ded4930842b46e9507372f0b1b963James Dong            {
2220c1bc742181ded4930842b46e9507372f0b1b963James Dong                m [j * 4 + i]  = Buf [j * 4 + i] * (1 << QPper) *
2230c1bc742181ded4930842b46e9507372f0b1b963James Dong                    armVCM4P10_VMatrix[QPmod][armVCM4P10_PosToVCol4x4[j * 4 + i]];
2240c1bc742181ded4930842b46e9507372f0b1b963James Dong            }
2250c1bc742181ded4930842b46e9507372f0b1b963James Dong        }
2260c1bc742181ded4930842b46e9507372f0b1b963James Dong        armVCM4P10_TransformResidual4x4 (pDstDeQuantCoeff, m);
2270c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
2280c1bc742181ded4930842b46e9507372f0b1b963James Dong
2290c1bc742181ded4930842b46e9507372f0b1b963James Dong    return OMX_Sts_NoErr;
2300c1bc742181ded4930842b46e9507372f0b1b963James Dong}
2310c1bc742181ded4930842b46e9507372f0b1b963James Dong
2320c1bc742181ded4930842b46e9507372f0b1b963James Dong/*****************************************************************************
2330c1bc742181ded4930842b46e9507372f0b1b963James Dong *                              END OF FILE
2340c1bc742181ded4930842b46e9507372f0b1b963James Dong *****************************************************************************/
2350c1bc742181ded4930842b46e9507372f0b1b963James Dong
236