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