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:  armVCM4P2_ACDCPredict.c
20 * OpenMAX DL: v1.0.2
21 * Revision:   9641
22 * Date:       Thursday, February 7, 2008
23 *
24 *
25 *
26 *
27 * Description:
28 * Contains module for DC/AC coefficient prediction
29 *
30 */
31
32#include "omxtypes.h"
33#include "armOMX.h"
34
35#include "armVC.h"
36#include "armCOMM.h"
37
38/**
39 * Function: armVCM4P2_ACDCPredict
40 *
41 * Description:
42 * Performs adaptive DC/AC coefficient prediction for an intra block. Prior
43 * to the function call, prediction direction (predDir) should be selected
44 * as specified in subclause 7.4.3.1 of ISO/IEC 14496-2.
45 *
46 * Remarks:
47 *
48 * Parameters:
49 * [in] pSrcDst     pointer to the coefficient buffer which contains
50 *                          the quantized coefficient residuals (PQF) of the
51 *                          current block
52 * [in] pPredBufRow pointer to the coefficient row buffer
53 * [in] pPredBufCol pointer to the coefficient column buffer
54 * [in] curQP       quantization parameter of the current block. curQP
55 *                          may equal to predQP especially when the current
56 *                          block and the predictor block are in the same
57 *                          macroblock.
58 * [in] predQP      quantization parameter of the predictor block
59 * [in] predDir     indicates the prediction direction which takes one
60 *                          of the following values:
61 *                          OMX_VC_HORIZONTAL    predict horizontally
62 *                          OMX_VC_VERTICAL      predict vertically
63 * [in] ACPredFlag  a flag indicating if AC prediction should be
64 *                          performed. It is equal to ac_pred_flag in the bit
65 *                          stream syntax of MPEG-4
66 * [in] videoComp   video component type (luminance, chrominance or
67 *                          alpha) of the current block
68 * [in] flag        This flag defines the if one wants to use this functions to
69 *                  calculate PQF (set 1, prediction) or QF (set 0, reconstruction)
70 * [out]    pPreACPredict   pointer to the predicted coefficients buffer.
71 *                          Filled ONLY if it is not NULL
72 * [out]    pSrcDst     pointer to the coefficient buffer which contains
73 *                          the quantized coefficients (QF) of the current
74 *                          block
75 * [out]    pPredBufRow pointer to the updated coefficient row buffer
76 * [out]    pPredBufCol pointer to the updated coefficient column buffer
77 * [out]    pSumErr     pointer to the updated sum of the difference
78 *                      between predicted and unpredicted coefficients
79 *                      If this is NULL, do not update
80 *
81 * Return Value:
82 * Standard OMXResult result. See enumeration for possible result codes.
83 *
84 */
85
86OMXResult armVCM4P2_ACDCPredict(
87     OMX_S16 * pSrcDst,
88     OMX_S16 * pPreACPredict,
89     OMX_S16 * pPredBufRow,
90     OMX_S16 * pPredBufCol,
91     OMX_INT curQP,
92     OMX_INT predQP,
93     OMX_INT predDir,
94     OMX_INT ACPredFlag,
95     OMXVCM4P2VideoComponent videoComp,
96     OMX_U8 flag,
97     OMX_INT *pSumErr
98)
99{
100    OMX_INT dcScaler, i;
101    OMX_S16 tempPred;
102
103    /* Argument error checks */
104    armRetArgErrIf(pSrcDst == NULL, OMX_Sts_BadArgErr);
105    armRetArgErrIf(pPredBufRow == NULL, OMX_Sts_BadArgErr);
106    armRetArgErrIf(pPredBufCol == NULL, OMX_Sts_BadArgErr);
107    armRetArgErrIf(curQP <= 0, OMX_Sts_BadArgErr);
108    armRetArgErrIf(predQP <= 0, OMX_Sts_BadArgErr);
109    armRetArgErrIf((predDir != 1) && (predDir != 2), OMX_Sts_BadArgErr);
110    armRetArgErrIf(!armIs4ByteAligned(pSrcDst), OMX_Sts_BadArgErr);
111    armRetArgErrIf(!armIs4ByteAligned(pPredBufRow), OMX_Sts_BadArgErr);
112    armRetArgErrIf(!armIs4ByteAligned(pPredBufCol), OMX_Sts_BadArgErr);
113
114
115    /* Set DC scaler value to avoid some compilers giving a warning. */
116    dcScaler=0;
117
118    /* Calculate the DC scaler value */
119    if (videoComp == OMX_VC_LUMINANCE)
120    {
121        if (curQP >= 1 && curQP <= 4)
122        {
123            dcScaler = 8;
124        }
125        else if (curQP >= 5 && curQP <= 8)
126        {
127            dcScaler = 2 * curQP;
128        }
129        else if (curQP >= 9 && curQP <= 24)
130        {
131            dcScaler = curQP + 8;
132        }
133        else
134        {
135            dcScaler = (2 * curQP) - 16;
136        }
137    }
138    else if (videoComp == OMX_VC_CHROMINANCE)
139    {
140        if (curQP >= 1 && curQP <= 4)
141        {
142            dcScaler = 8;
143        }
144        else if (curQP >= 5 && curQP <= 24)
145        {
146            dcScaler = (curQP + 13)/2;
147        }
148        else
149        {
150            dcScaler = curQP - 6;
151        }
152    }
153
154    if (pPreACPredict != NULL)
155    {
156        pPreACPredict[0] = predDir;
157    }
158
159    if (predDir == OMX_VC_VERTICAL)
160    {
161        /* F[0][0]//dc_scaler */
162        tempPred = armIntDivAwayFromZero(pPredBufRow[0], dcScaler);
163    }
164    else
165    {
166        /* F[0][0]//dc_scaler */
167        tempPred = armIntDivAwayFromZero(pPredBufCol[0], dcScaler);
168    }
169
170    /* Updating the DC value to the row and col buffer */
171    *(pPredBufRow - 8) = *pPredBufCol;
172
173    if (flag)
174    {
175        /* Cal and store F[0][0] into the col buffer */
176        *pPredBufCol = pSrcDst[0] * dcScaler;
177
178        /* PQF = QF - F[0][0]//dc_scaler */
179        pSrcDst[0] -= tempPred;
180    }
181    else
182    {
183        /* QF = PQF + F[0][0]//dc_scaler */
184        pSrcDst[0] += tempPred;
185
186        /* Saturate */
187        pSrcDst[0] = armClip (-2048, 2047, pSrcDst[0]);
188
189        /* Cal and store F[0][0] into the col buffer */
190        *pPredBufCol = pSrcDst[0] * dcScaler;
191    }
192
193
194    if (ACPredFlag == 1)
195    {
196        if (predDir == OMX_VC_VERTICAL)
197        {
198            for (i = 1; i < 8; i++)
199            {
200                tempPred = armIntDivAwayFromZero \
201                              (pPredBufRow[i] * predQP, curQP);
202                if (flag)
203                {
204                    /* Updating QF to the row buff */
205                    pPredBufRow[i] = pSrcDst[i];
206                    /*PQFX[v][0] = QFX[v][0] - (QFA[v][0] * QPA) // QPX */
207                    pSrcDst[i] -= tempPred;
208                    /* Sum of absolute values of AC prediction error, this can
209                    be used as a reference to choose whether to use
210                    AC prediction */
211                    *pSumErr += armAbs(pSrcDst[i]);
212                    /* pPreACPredict[1~7] store the error signal
213                    after AC prediction */
214                    pPreACPredict[i] = pSrcDst[i];
215                }
216                else
217                {
218                    /*QFX[v][0] = PQFX[v][0] + (QFA[v][0] * QPA) // QPX */
219                    pSrcDst[i] += tempPred;
220
221                    /* Saturate */
222                    pSrcDst[i] = armClip (-2048, 2047, pSrcDst[i]);
223
224                    /* Updating QF to the row buff */
225                    pPredBufRow[i] = pSrcDst[i];
226                }
227            }
228        }
229        else
230        {
231            for (i = 8; i < 64; i += 8)
232            {
233                tempPred = armIntDivAwayFromZero \
234                              (pPredBufCol[i>>3] * predQP, curQP);
235                if (flag)
236                {
237                    /* Updating QF to col buff */
238                    pPredBufCol[i>>3] = pSrcDst[i];
239                    /*PQFX[0][u] = QFX[0][u] - (QFA[0][u] * QPA) // QPX */
240                    pSrcDst[i] -= tempPred;
241                    /* Sum of absolute values of AC prediction error, this can
242                    be used as a reference to choose whether to use AC
243                    prediction */
244                    *pSumErr += armAbs(pSrcDst[i]);
245                    /* pPreACPredict[1~7] store the error signal
246                    after AC prediction */
247                    pPreACPredict[i>>3] = pSrcDst[i];
248                }
249                else
250                {
251                    /*QFX[0][u] = PQFX[0][u] + (QFA[0][u] * QPA) // QPX */
252                    pSrcDst[i] += tempPred;
253
254                    /* Saturate */
255                    pSrcDst[i] = armClip (-2048, 2047, pSrcDst[i]);
256
257                    /* Updating QF to col buff */
258                    pPredBufCol[i>>3] = pSrcDst[i];
259                }
260            }
261        }
262    }
263
264    return OMX_Sts_NoErr;
265}
266
267/*End of File*/
268
269