summaryrefslogtreecommitdiffstats
path: root/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_SubAndTransformQDQResidual.c
blob: 23a5662e20957354784bf33aca9b5a84f76b9d59 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
/**
 * 
 * File Name:  omxVCM4P10_SubAndTransformQDQResidual.c
 * OpenMAX DL: v1.0.2
 * Revision:   9641
 * Date:       Thursday, February 7, 2008
 * 
 * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 * 
 * 
 * Description:
 * This function will calculate SAD for 4x4 blocks
 * 
 */

#include "omxtypes.h"
#include "armOMX.h"
#include "omxVC.h"

#include "armCOMM.h"
#include "armVC.h"

/**
 * Function:  omxVCM4P10_SubAndTransformQDQResidual   (6.3.5.8.1)
 *
 * Description:
 * This function subtracts the prediction signal from the original signal to 
 * produce the difference signal and then performs a 4x4 integer transform and 
 * quantization. The quantized transformed coefficients are stored as 
 * pDstQuantCoeff. This function can also output dequantized coefficients or 
 * unquantized DC coefficients optionally by setting the pointers 
 * pDstDeQuantCoeff, pDCCoeff. 
 *
 * Input Arguments:
 *   
 *   pSrcOrg - Pointer to original signal. 4-byte alignment required. 
 *   pSrcPred - Pointer to prediction signal. 4-byte alignment required. 
 *   iSrcOrgStep - Step of the original signal buffer; must be a multiple of 
 *            4. 
 *   iSrcPredStep - Step of the prediction signal buffer; must be a multiple 
 *            of 4. 
 *   pNumCoeff -Number of non-zero coefficients after quantization. If this 
 *            parameter is not required, it is set to NULL. 
 *   nThreshSAD - Zero-block early detection threshold. If this parameter is 
 *            not required, it is set to 0. 
 *   iQP - Quantization parameter; must be in the range [0,51]. 
 *   bIntra - Indicates whether this is an INTRA block, either 1-INTRA or 
 *            0-INTER 
 *
 * Output Arguments:
 *   
 *   pDstQuantCoeff - Pointer to the quantized transformed coefficients.  
 *            8-byte alignment required. 
 *   pDstDeQuantCoeff - Pointer to the dequantized transformed coefficients 
 *            if this parameter is not equal to NULL.  8-byte alignment 
 *            required. 
 *   pDCCoeff - Pointer to the unquantized DC coefficient if this parameter 
 *            is not equal to NULL. 
 *
 * 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: 
 *            pSrcOrg, pSrcPred, pNumCoeff, pDstQuantCoeff, 
 *            pDstDeQuantCoeff, pDCCoeff 
 *    -    pSrcOrg is not aligned on a 4-byte boundary 
 *    -    pSrcPred is not aligned on a 4-byte boundary 
 *    -    iSrcOrgStep is not a multiple of 4 
 *    -    iSrcPredStep is not a multiple of 4 
 *    -    pDstQuantCoeff or pDstDeQuantCoeff is not aligned on an 8-byte boundary 
 *
 */
 OMXResult omxVCM4P10_SubAndTransformQDQResidual (
	 const OMX_U8*		pSrcOrg,
	 const OMX_U8*		pSrcPred,
	 OMX_U32		iSrcOrgStep,
	 OMX_U32		iSrcPredStep,
	 OMX_S16*	    pDstQuantCoeff,
	 OMX_S16* 	    pDstDeQuantCoeff,
	 OMX_S16*	    pDCCoeff,
	 OMX_S8*		pNumCoeff,
	 OMX_U32		nThreshSAD,
	 OMX_U32		iQP,
	 OMX_U8		    bIntra
)
{
    OMX_INT     i, j;
    OMX_S8      NumCoeff = 0;
    OMX_S16     Buf[16], m[16];
    OMX_U32     QBits, QPper, QPmod, f;
    OMX_S32     Value, MF, ThreshDC;

    /* check for argument error */
    armRetArgErrIf(pSrcOrg == NULL, OMX_Sts_BadArgErr)
	armRetArgErrIf(pDstDeQuantCoeff == NULL, OMX_Sts_BadArgErr)
	armRetArgErrIf(pNumCoeff == NULL, OMX_Sts_BadArgErr)
	armRetArgErrIf(pDCCoeff == NULL, OMX_Sts_BadArgErr)
    armRetArgErrIf(armNot4ByteAligned(pSrcOrg), OMX_Sts_BadArgErr)
    armRetArgErrIf(pSrcPred == NULL, OMX_Sts_BadArgErr)
    armRetArgErrIf(armNot4ByteAligned(pSrcPred), OMX_Sts_BadArgErr)
    armRetArgErrIf(pDstQuantCoeff == NULL, OMX_Sts_BadArgErr)
    armRetArgErrIf(armNot8ByteAligned(pDstQuantCoeff), OMX_Sts_BadArgErr)
    armRetArgErrIf((pDstDeQuantCoeff != NULL) && 
			armNot8ByteAligned(pDstDeQuantCoeff), OMX_Sts_BadArgErr)
    armRetArgErrIf((bIntra != 0) && (bIntra != 1), OMX_Sts_BadArgErr)
    armRetArgErrIf(iQP > 51, OMX_Sts_BadArgErr)
    armRetArgErrIf(iSrcOrgStep == 0, OMX_Sts_BadArgErr)
    armRetArgErrIf(iSrcPredStep == 0, OMX_Sts_BadArgErr)
    armRetArgErrIf(iSrcOrgStep & 3, OMX_Sts_BadArgErr)
    armRetArgErrIf(iSrcPredStep & 3, OMX_Sts_BadArgErr)

    /* 
     * Zero-Block Early detection using nThreshSAD param 
     */

    QPper = iQP / 6;
    QPmod = iQP % 6;    
    QBits = 15 + QPper;
    
    f = (1 << QBits) / (bIntra ? 3 : 6);
    
    /* Do Zero-Block Early detection if enabled */
    if (nThreshSAD)
    {
        ThreshDC = ((1 << QBits) - f) / armVCM4P10_MFMatrix[QPmod][0];
        if (nThreshSAD < ThreshDC)
        {
            /* Set block to zero */
            if (pDCCoeff != NULL)
            {
                *pDCCoeff = 0;
            }

            for (j = 0; j < 4; j++)
            {
                for (i = 0; i < 4; i++)
                {
                    pDstQuantCoeff [4 * j + i] = 0;
                    if (pDstDeQuantCoeff != NULL)
                    {
                        pDstDeQuantCoeff [4 * j + i] = 0;    
                    }                    
                }
            }

            if (pNumCoeff != NULL)
            {
                *pNumCoeff = 0;
            }
            return OMX_Sts_NoErr;
        }
    }


   /* Calculate difference */
    for (j = 0; j < 4; j++)
    {
        for (i = 0; i < 4; i++)
        {
            Buf [j * 4 + i] = 
                pSrcOrg [j * iSrcOrgStep + i] - pSrcPred [j * iSrcPredStep + i];
        }
    }

    /* Residual Transform */
    armVCM4P10_FwdTransformResidual4x4 (m, Buf);

    if (pDCCoeff != NULL)
    {
        /* Copy unquantized DC value into pointer */
        *pDCCoeff = m[0];
    }

    /* Quantization */
    for (j = 0; j < 4; j++)
    {
        for (i = 0; i < 4; i++)
        {
            MF = armVCM4P10_MFMatrix[QPmod][armVCM4P10_PosToVCol4x4[j * 4 + i]];
            Value = armAbs(m[j * 4 + i]) * MF + f;
            Value >>= QBits;
            Value = m[j * 4 + i] < 0 ? -Value : Value;
            Buf[4 * j + i] = pDstQuantCoeff [4 * j + i] = (OMX_S16)Value;
            if ((pNumCoeff != NULL) && Value)
            {
                NumCoeff++;
            }
        }
    }

    /* Output number of non-zero Coeffs */
    if (pNumCoeff != NULL)
    {
        *pNumCoeff = NumCoeff;
    }
    
    /* Residual Inv Transform */
    if (pDstDeQuantCoeff != NULL)
    {    
        /* Re Scale */
        for (j = 0; j < 4; j++)
        {
            for (i = 0; i < 4; i++)
            {
                m [j * 4 + i]  = Buf [j * 4 + i] * (1 << QPper) *
                    armVCM4P10_VMatrix[QPmod][armVCM4P10_PosToVCol4x4[j * 4 + i]];
            }
        }
        armVCM4P10_TransformResidual4x4 (pDstDeQuantCoeff, m);        
    }
        
    return OMX_Sts_NoErr;
}

/*****************************************************************************
 *                              END OF FILE
 *****************************************************************************/