omxVCM4P10_SubAndTransformQDQResidual.c revision 0c1bc742181ded4930842b46e9507372f0b1b963
1/**
2 *
3 * File Name:  omxVCM4P10_SubAndTransformQDQResidual.c
4 * OpenMAX DL: v1.0.2
5 * Revision:   9641
6 * Date:       Thursday, February 7, 2008
7 *
8 * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
9 *
10 *
11 * Description:
12 * This function will calculate SAD for 4x4 blocks
13 *
14 */
15
16#include "omxtypes.h"
17#include "armOMX.h"
18#include "omxVC.h"
19
20#include "armCOMM.h"
21#include "armVC.h"
22
23/**
24 * Function:  omxVCM4P10_SubAndTransformQDQResidual   (6.3.5.8.1)
25 *
26 * Description:
27 * This function subtracts the prediction signal from the original signal to
28 * produce the difference signal and then performs a 4x4 integer transform and
29 * quantization. The quantized transformed coefficients are stored as
30 * pDstQuantCoeff. This function can also output dequantized coefficients or
31 * unquantized DC coefficients optionally by setting the pointers
32 * pDstDeQuantCoeff, pDCCoeff.
33 *
34 * Input Arguments:
35 *
36 *   pSrcOrg - Pointer to original signal. 4-byte alignment required.
37 *   pSrcPred - Pointer to prediction signal. 4-byte alignment required.
38 *   iSrcOrgStep - Step of the original signal buffer; must be a multiple of
39 *            4.
40 *   iSrcPredStep - Step of the prediction signal buffer; must be a multiple
41 *            of 4.
42 *   pNumCoeff -Number of non-zero coefficients after quantization. If this
43 *            parameter is not required, it is set to NULL.
44 *   nThreshSAD - Zero-block early detection threshold. If this parameter is
45 *            not required, it is set to 0.
46 *   iQP - Quantization parameter; must be in the range [0,51].
47 *   bIntra - Indicates whether this is an INTRA block, either 1-INTRA or
48 *            0-INTER
49 *
50 * Output Arguments:
51 *
52 *   pDstQuantCoeff - Pointer to the quantized transformed coefficients.
53 *            8-byte alignment required.
54 *   pDstDeQuantCoeff - Pointer to the dequantized transformed coefficients
55 *            if this parameter is not equal to NULL.  8-byte alignment
56 *            required.
57 *   pDCCoeff - Pointer to the unquantized DC coefficient if this parameter
58 *            is not equal to NULL.
59 *
60 * Return Value:
61 *
62 *    OMX_Sts_NoErr - no error
63 *    OMX_Sts_BadArgErr - bad arguments; returned if any of the following
64 *              conditions are true:
65 *    -    at least one of the following pointers is NULL:
66 *            pSrcOrg, pSrcPred, pNumCoeff, pDstQuantCoeff,
67 *            pDstDeQuantCoeff, pDCCoeff
68 *    -    pSrcOrg is not aligned on a 4-byte boundary
69 *    -    pSrcPred is not aligned on a 4-byte boundary
70 *    -    iSrcOrgStep is not a multiple of 4
71 *    -    iSrcPredStep is not a multiple of 4
72 *    -    pDstQuantCoeff or pDstDeQuantCoeff is not aligned on an 8-byte boundary
73 *
74 */
75 OMXResult omxVCM4P10_SubAndTransformQDQResidual (
76	 const OMX_U8*		pSrcOrg,
77	 const OMX_U8*		pSrcPred,
78	 OMX_U32		iSrcOrgStep,
79	 OMX_U32		iSrcPredStep,
80	 OMX_S16*	    pDstQuantCoeff,
81	 OMX_S16* 	    pDstDeQuantCoeff,
82	 OMX_S16*	    pDCCoeff,
83	 OMX_S8*		pNumCoeff,
84	 OMX_U32		nThreshSAD,
85	 OMX_U32		iQP,
86	 OMX_U8		    bIntra
87)
88{
89    OMX_INT     i, j;
90    OMX_S8      NumCoeff = 0;
91    OMX_S16     Buf[16], m[16];
92    OMX_U32     QBits, QPper, QPmod, f;
93    OMX_S32     Value, MF, ThreshDC;
94
95    /* check for argument error */
96    armRetArgErrIf(pSrcOrg == NULL, OMX_Sts_BadArgErr)
97	armRetArgErrIf(pDstDeQuantCoeff == NULL, OMX_Sts_BadArgErr)
98	armRetArgErrIf(pNumCoeff == NULL, OMX_Sts_BadArgErr)
99	armRetArgErrIf(pDCCoeff == NULL, OMX_Sts_BadArgErr)
100    armRetArgErrIf(armNot4ByteAligned(pSrcOrg), OMX_Sts_BadArgErr)
101    armRetArgErrIf(pSrcPred == NULL, OMX_Sts_BadArgErr)
102    armRetArgErrIf(armNot4ByteAligned(pSrcPred), OMX_Sts_BadArgErr)
103    armRetArgErrIf(pDstQuantCoeff == NULL, OMX_Sts_BadArgErr)
104    armRetArgErrIf(armNot8ByteAligned(pDstQuantCoeff), OMX_Sts_BadArgErr)
105    armRetArgErrIf((pDstDeQuantCoeff != NULL) &&
106			armNot8ByteAligned(pDstDeQuantCoeff), OMX_Sts_BadArgErr)
107    armRetArgErrIf((bIntra != 0) && (bIntra != 1), OMX_Sts_BadArgErr)
108    armRetArgErrIf(iQP > 51, OMX_Sts_BadArgErr)
109    armRetArgErrIf(iSrcOrgStep == 0, OMX_Sts_BadArgErr)
110    armRetArgErrIf(iSrcPredStep == 0, OMX_Sts_BadArgErr)
111    armRetArgErrIf(iSrcOrgStep & 3, OMX_Sts_BadArgErr)
112    armRetArgErrIf(iSrcPredStep & 3, OMX_Sts_BadArgErr)
113
114    /*
115     * Zero-Block Early detection using nThreshSAD param
116     */
117
118    QPper = iQP / 6;
119    QPmod = iQP % 6;
120    QBits = 15 + QPper;
121
122    f = (1 << QBits) / (bIntra ? 3 : 6);
123
124    /* Do Zero-Block Early detection if enabled */
125    if (nThreshSAD)
126    {
127        ThreshDC = ((1 << QBits) - f) / armVCM4P10_MFMatrix[QPmod][0];
128        if (nThreshSAD < ThreshDC)
129        {
130            /* Set block to zero */
131            if (pDCCoeff != NULL)
132            {
133                *pDCCoeff = 0;
134            }
135
136            for (j = 0; j < 4; j++)
137            {
138                for (i = 0; i < 4; i++)
139                {
140                    pDstQuantCoeff [4 * j + i] = 0;
141                    if (pDstDeQuantCoeff != NULL)
142                    {
143                        pDstDeQuantCoeff [4 * j + i] = 0;
144                    }
145                }
146            }
147
148            if (pNumCoeff != NULL)
149            {
150                *pNumCoeff = 0;
151            }
152            return OMX_Sts_NoErr;
153        }
154    }
155
156
157   /* Calculate difference */
158    for (j = 0; j < 4; j++)
159    {
160        for (i = 0; i < 4; i++)
161        {
162            Buf [j * 4 + i] =
163                pSrcOrg [j * iSrcOrgStep + i] - pSrcPred [j * iSrcPredStep + i];
164        }
165    }
166
167    /* Residual Transform */
168    armVCM4P10_FwdTransformResidual4x4 (m, Buf);
169
170    if (pDCCoeff != NULL)
171    {
172        /* Copy unquantized DC value into pointer */
173        *pDCCoeff = m[0];
174    }
175
176    /* Quantization */
177    for (j = 0; j < 4; j++)
178    {
179        for (i = 0; i < 4; i++)
180        {
181            MF = armVCM4P10_MFMatrix[QPmod][armVCM4P10_PosToVCol4x4[j * 4 + i]];
182            Value = armAbs(m[j * 4 + i]) * MF + f;
183            Value >>= QBits;
184            Value = m[j * 4 + i] < 0 ? -Value : Value;
185            Buf[4 * j + i] = pDstQuantCoeff [4 * j + i] = (OMX_S16)Value;
186            if ((pNumCoeff != NULL) && Value)
187            {
188                NumCoeff++;
189            }
190        }
191    }
192
193    /* Output number of non-zero Coeffs */
194    if (pNumCoeff != NULL)
195    {
196        *pNumCoeff = NumCoeff;
197    }
198
199    /* Residual Inv Transform */
200    if (pDstDeQuantCoeff != NULL)
201    {
202        /* Re Scale */
203        for (j = 0; j < 4; j++)
204        {
205            for (i = 0; i < 4; i++)
206            {
207                m [j * 4 + i]  = Buf [j * 4 + i] * (1 << QPper) *
208                    armVCM4P10_VMatrix[QPmod][armVCM4P10_PosToVCol4x4[j * 4 + i]];
209            }
210        }
211        armVCM4P10_TransformResidual4x4 (pDstDeQuantCoeff, m);
212    }
213
214    return OMX_Sts_NoErr;
215}
216
217/*****************************************************************************
218 *                              END OF FILE
219 *****************************************************************************/
220
221