omxVCM4P10_PredictIntra_4x4.c revision 0c1bc742181ded4930842b46e9507372f0b1b963
1/* ----------------------------------------------------------------
2 *
3 *
4 * File Name:  omxVCM4P10_PredictIntra_4x4.c
5 * OpenMAX DL: v1.0.2
6 * Revision:   9641
7 * Date:       Thursday, February 7, 2008
8 *
9 * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
10 *
11 *
12 *
13 * H.264 4x4 intra prediction module
14 *
15 */
16
17#include "omxtypes.h"
18#include "armOMX.h"
19#include "omxVC.h"
20
21#include "armCOMM.h"
22#include "armVC.h"
23
24/**
25 * Function:  omxVCM4P10_PredictIntra_4x4   (6.3.3.1.1)
26 *
27 * Description:
28 * Perform Intra_4x4 prediction for luma samples. If the upper-right block is
29 * not available, then duplication work should be handled inside the function.
30 * Users need not define them outside.
31 *
32 * Input Arguments:
33 *
34 *   pSrcLeft -  Pointer to the buffer of 4 left pixels:
35 *                  p[x, y] (x = -1, y = 0..3)
36 *   pSrcAbove - Pointer to the buffer of 8 above pixels:
37 *                  p[x,y] (x = 0..7, y =-1);
38 *               must be aligned on a 4-byte boundary.
39 *   pSrcAboveLeft - Pointer to the above left pixels: p[x,y] (x = -1, y = -1)
40 *   leftStep - Step of left pixel buffer; must be a multiple of 4.
41 *   dstStep - Step of the destination buffer; must be a multiple of 4.
42 *   predMode - Intra_4x4 prediction mode.
43 *   availability - Neighboring 4x4 block availability flag, refer to
44 *             "Neighboring Macroblock Availability" .
45 *
46 * Output Arguments:
47 *
48 *   pDst - Pointer to the destination buffer; must be aligned on a 4-byte
49 *            boundary.
50 *
51 * Return Value:
52 *    If the function runs without error, it returns OMX_Sts_NoErr.
53 *    If one of the following cases occurs, the function returns
54 *              OMX_Sts_BadArgErr:
55 *    pDst is NULL.
56 *    dstStep < 4, or dstStep is not a multiple of 4.
57 *    leftStep is not a multiple of 4.
58 *    predMode is not in the valid range of enumeration
59 *              OMXVCM4P10Intra4x4PredMode.
60 *    predMode is OMX_VC_4x4_VERT, but availability doesn't set OMX_VC_UPPER
61 *              indicating p[x,-1] (x = 0..3) is not available.
62 *    predMode is OMX_VC_4x4_HOR, but availability doesn't set OMX_VC_LEFT
63 *              indicating p[-1,y] (y = 0..3) is not available.
64 *    predMode is OMX_VC_4x4_DIAG_DL, but availability doesn't set
65 *              OMX_VC_UPPER indicating p[x, 1] (x = 0..3) is not available.
66 *    predMode is OMX_VC_4x4_DIAG_DR, but availability doesn't set
67 *              OMX_VC_UPPER_LEFT or OMX_VC_UPPER or OMX_VC_LEFT indicating
68 *              p[x,-1] (x = 0..3), or p[-1,y] (y = 0..3) or p[-1,-1] is not
69 *              available.
70 *    predMode is OMX_VC_4x4_VR, but availability doesn't set
71 *              OMX_VC_UPPER_LEFT or OMX_VC_UPPER or OMX_VC_LEFT indicating
72 *              p[x,-1] (x = 0..3), or p[-1,y] (y = 0..3) or p[-1,-1] is not
73 *              available.
74 *    predMode is OMX_VC_4x4_HD, but availability doesn't set
75 *              OMX_VC_UPPER_LEFT or OMX_VC_UPPER or OMX_VC_LEFT indicating
76 *              p[x,-1] (x = 0..3), or p[-1,y] (y = 0..3) or p[-1,-1] is not
77 *              available.
78 *    predMode is OMX_VC_4x4_VL, but availability doesn't set OMX_VC_UPPER
79 *              indicating p[x,-1] (x = 0..3) is not available.
80 *    predMode is OMX_VC_4x4_HU, but availability doesn't set OMX_VC_LEFT
81 *              indicating p[-1,y] (y = 0..3) is not available.
82 *    availability sets OMX_VC_UPPER, but pSrcAbove is NULL.
83 *    availability sets OMX_VC_LEFT, but pSrcLeft is NULL.
84 *    availability sets OMX_VC_UPPER_LEFT, but pSrcAboveLeft is NULL.
85 *    either pSrcAbove or pDst is not aligned on a 4-byte boundary.
86 *
87 * Note:
88 *     pSrcAbove, pSrcAbove, pSrcAboveLeft may be invalid pointers if
89 *     they are not used by intra prediction as implied in predMode.
90 *
91 */
92
93OMXResult omxVCM4P10_PredictIntra_4x4(
94     const OMX_U8* pSrcLeft,
95     const OMX_U8 *pSrcAbove,
96     const OMX_U8 *pSrcAboveLeft,
97     OMX_U8* pDst,
98     OMX_INT leftStep,
99     OMX_INT dstStep,
100     OMXVCM4P10Intra4x4PredMode predMode,
101     OMX_S32 availability
102 )
103{
104    int x, y;
105    OMX_U8 pTmp[10];
106
107    armRetArgErrIf(pDst == NULL, OMX_Sts_BadArgErr);
108    armRetArgErrIf((leftStep % 4) != 0,  OMX_Sts_BadArgErr);
109    armRetArgErrIf((dstStep % 4) != 0,  OMX_Sts_BadArgErr);
110    armRetArgErrIf((dstStep < 4),  OMX_Sts_BadArgErr);
111    armRetArgErrIf(armNot4ByteAligned(pSrcAbove), OMX_Sts_BadArgErr);
112    armRetArgErrIf(armNot4ByteAligned(pDst), OMX_Sts_BadArgErr);
113    armRetArgErrIf((availability & OMX_VC_UPPER)      && pSrcAbove     == NULL, OMX_Sts_BadArgErr);
114    armRetArgErrIf((availability & OMX_VC_LEFT )      && pSrcLeft      == NULL, OMX_Sts_BadArgErr);
115    armRetArgErrIf((availability & OMX_VC_UPPER_LEFT) && pSrcAboveLeft == NULL, OMX_Sts_BadArgErr);
116    armRetArgErrIf(predMode==OMX_VC_4X4_VERT    && !(availability & OMX_VC_UPPER),      OMX_Sts_BadArgErr);
117    armRetArgErrIf(predMode==OMX_VC_4X4_HOR     && !(availability & OMX_VC_LEFT),       OMX_Sts_BadArgErr);
118    armRetArgErrIf(predMode==OMX_VC_4X4_DIAG_DL && !(availability & OMX_VC_UPPER),      OMX_Sts_BadArgErr);
119    armRetArgErrIf(predMode==OMX_VC_4X4_DIAG_DR && !(availability & OMX_VC_UPPER),      OMX_Sts_BadArgErr);
120    armRetArgErrIf(predMode==OMX_VC_4X4_DIAG_DR && !(availability & OMX_VC_UPPER_LEFT), OMX_Sts_BadArgErr);
121    armRetArgErrIf(predMode==OMX_VC_4X4_DIAG_DR && !(availability & OMX_VC_LEFT),       OMX_Sts_BadArgErr);
122    armRetArgErrIf(predMode==OMX_VC_4X4_VR      && !(availability & OMX_VC_UPPER),      OMX_Sts_BadArgErr);
123    armRetArgErrIf(predMode==OMX_VC_4X4_VR      && !(availability & OMX_VC_UPPER_LEFT), OMX_Sts_BadArgErr);
124    armRetArgErrIf(predMode==OMX_VC_4X4_VR      && !(availability & OMX_VC_LEFT),       OMX_Sts_BadArgErr);
125    armRetArgErrIf(predMode==OMX_VC_4X4_HD      && !(availability & OMX_VC_UPPER),      OMX_Sts_BadArgErr);
126    armRetArgErrIf(predMode==OMX_VC_4X4_HD      && !(availability & OMX_VC_UPPER_LEFT), OMX_Sts_BadArgErr);
127    armRetArgErrIf(predMode==OMX_VC_4X4_HD      && !(availability & OMX_VC_LEFT),       OMX_Sts_BadArgErr);
128    armRetArgErrIf(predMode==OMX_VC_4X4_VL      && !(availability & OMX_VC_UPPER),      OMX_Sts_BadArgErr);
129    armRetArgErrIf(predMode==OMX_VC_4X4_HU      && !(availability & OMX_VC_LEFT),       OMX_Sts_BadArgErr);
130    armRetArgErrIf((unsigned)predMode > OMX_VC_4X4_HU,   OMX_Sts_BadArgErr);
131
132    /* Note: This code must not read the pSrc arrays unless the corresponding
133     * block is marked as available. If the block is not avaibable then pSrc
134     * may not be a valid pointer.
135     *
136     * Note: To make the code more readable we refer to the neighbouring pixels
137     * in variables named as below:
138     *
139     *    UL U0 U1 U2 U3 U4 U5 U6 U7
140     *    L0 xx xx xx xx
141     *    L1 xx xx xx xx
142     *    L2 xx xx xx xx
143     *    L3 xx xx xx xx
144     */
145
146#define UL pSrcAboveLeft[0]
147#define U0 pSrcAbove[0]
148#define U1 pSrcAbove[1]
149#define U2 pSrcAbove[2]
150#define U3 pSrcAbove[3]
151#define U4 pSrcAbove[4]
152#define U5 pSrcAbove[5]
153#define U6 pSrcAbove[6]
154#define U7 pSrcAbove[7]
155#define L0 pSrcLeft[0*leftStep]
156#define L1 pSrcLeft[1*leftStep]
157#define L2 pSrcLeft[2*leftStep]
158#define L3 pSrcLeft[3*leftStep]
159
160    switch (predMode)
161    {
162    case OMX_VC_4X4_VERT:
163        for (y=0; y<4; y++)
164        {
165            pDst[y*dstStep+0] = U0;
166            pDst[y*dstStep+1] = U1;
167            pDst[y*dstStep+2] = U2;
168            pDst[y*dstStep+3] = U3;
169        }
170        break;
171
172    case OMX_VC_4X4_HOR:
173        for (x=0; x<4; x++)
174        {
175            pDst[0*dstStep+x] = L0;
176            pDst[1*dstStep+x] = L1;
177            pDst[2*dstStep+x] = L2;
178            pDst[3*dstStep+x] = L3;
179        }
180        break;
181
182    case OMX_VC_4X4_DC:
183        /* This can always be used even if no blocks available */
184        armVCM4P10_PredictIntraDC4x4(pSrcLeft, pSrcAbove, pDst, leftStep, dstStep, availability);
185        break;
186
187    case OMX_VC_4X4_DIAG_DL:
188        pTmp[0] = (OMX_U8)((U0 + 2*U1 + U2 + 2)>>2);
189        pTmp[1] = (OMX_U8)((U1 + 2*U2 + U3 + 2)>>2);
190        if (availability & OMX_VC_UPPER_RIGHT)
191        {
192            pTmp[2] = (OMX_U8)((U2 + 2*U3 + U4 + 2)>>2);
193            pTmp[3] = (OMX_U8)((U3 + 2*U4 + U5 + 2)>>2);
194            pTmp[4] = (OMX_U8)((U4 + 2*U5 + U6 + 2)>>2);
195            pTmp[5] = (OMX_U8)((U5 + 2*U6 + U7 + 2)>>2);
196            pTmp[6] = (OMX_U8)((U6 + 3*U7      + 2)>>2);
197        }
198        else
199        {
200            pTmp[2] = (OMX_U8)((U2 + 3*U3      + 2)>>2);
201            pTmp[3] = U3;
202            pTmp[4] = U3;
203            pTmp[5] = U3;
204            pTmp[6] = U3;
205        }
206        for (y=0; y<4; y++)
207        {
208            for (x=0; x<4; x++)
209            {
210                pDst[y*dstStep+x] = pTmp[x+y];
211            }
212        }
213        break;
214
215    case OMX_VC_4X4_DIAG_DR:
216        /* x-y = -3, -2, -1, 0, 1, 2, 3 */
217        pTmp[0] = (OMX_U8)((L1 + 2*L2 + L3 + 2)>>2);
218        pTmp[1] = (OMX_U8)((L0 + 2*L1 + L2 + 2)>>2);
219        pTmp[2] = (OMX_U8)((UL + 2*L0 + L1 + 2)>>2);
220        pTmp[3] = (OMX_U8)((U0 + 2*UL + L0 + 2)>>2);
221        pTmp[4] = (OMX_U8)((U1 + 2*U0 + UL + 2)>>2);
222        pTmp[5] = (OMX_U8)((U2 + 2*U1 + U0 + 2)>>2);
223        pTmp[6] = (OMX_U8)((U3 + 2*U2 + U1 + 2)>>2);
224        for (y=0; y<4; y++)
225        {
226            for (x=0; x<4; x++)
227            {
228                pDst[y*dstStep+x] = pTmp[3+x-y];
229            }
230        }
231        break;
232
233    case OMX_VC_4X4_VR:
234        /* zVR=2x-y = -3, -2, -1, 0, 1, 2, 3, 4, 5, 6
235         * x-(y>>1) = -1, -1,  0, 0, 1, 1, 2, 2, 3, 3
236         * y        =  3,  2,  ?, ?, ?, ?, ?, ?, 1, 0
237         */
238        pTmp[0] = (OMX_U8)((L2 + 2*L1 + L0 + 2)>>2);
239        pTmp[1] = (OMX_U8)((L1 + 2*L0 + UL + 2)>>2);
240        pTmp[2] = (OMX_U8)((L0 + 2*UL + U0 + 2)>>2);
241        pTmp[3] = (OMX_U8)((UL + U0 + 1)>>1);
242        pTmp[4] = (OMX_U8)((UL + 2*U0 + U1 + 2)>>2);
243        pTmp[5] = (OMX_U8)((U0 + U1 + 1)>>1);
244        pTmp[6] = (OMX_U8)((U0 + 2*U1 + U2 + 2)>>2);
245        pTmp[7] = (OMX_U8)((U1 + U2 + 1)>>1);
246        pTmp[8] = (OMX_U8)((U1 + 2*U2 + U3 + 2)>>2);
247        pTmp[9] = (OMX_U8)((U2 + U3 + 1)>>1);
248        for (y=0; y<4; y++)
249        {
250            for (x=0; x<4; x++)
251            {
252                pDst[y*dstStep+x] = pTmp[3+2*x-y];
253            }
254        }
255        break;
256
257    case OMX_VC_4X4_HD:
258        /* zHD=2y-x = -3 -2 -1  0  1  2  3  4  5  6
259         * y-(x>>1) = -1 -1  0  0  1  1  2  2  3  3
260         * x        =  3  2                    1  0
261         */
262        pTmp[0] = (OMX_U8)((U2 + 2*U1 + U0 + 2)>>2);
263        pTmp[1] = (OMX_U8)((U1 + 2*U0 + UL + 2)>>2);
264        pTmp[2] = (OMX_U8)((U0 + 2*UL + L0 + 2)>>2);
265        pTmp[3] = (OMX_U8)((UL + L0 + 1)>>1);
266        pTmp[4] = (OMX_U8)((UL + 2*L0 + L1 + 2)>>2);
267        pTmp[5] = (OMX_U8)((L0 + L1 + 1)>>1);
268        pTmp[6] = (OMX_U8)((L0 + 2*L1 + L2 + 2)>>2);
269        pTmp[7] = (OMX_U8)((L1 + L2 + 1)>>1);
270        pTmp[8] = (OMX_U8)((L1 + 2*L2 + L3 + 2)>>2);
271        pTmp[9] = (OMX_U8)((L2 + L3 + 1)>>1);
272        for (y=0; y<4; y++)
273        {
274            for (x=0; x<4; x++)
275            {
276                pDst[y*dstStep+x] = pTmp[3+2*y-x];
277            }
278        }
279        break;
280
281    case OMX_VC_4X4_VL:
282        /* Note: x+(y>>1) = (2*x+y)>>1
283         * 2x+y = 0 1 2 3 4 5 6 7 8 9
284         */
285        pTmp[0] = (OMX_U8)((U0 + U1 + 1)>>1);
286        pTmp[1] = (OMX_U8)((U0 + 2*U1 + U2 + 2)>>2);
287        pTmp[2] = (OMX_U8)((U1 + U2 + 1)>>1);
288        pTmp[3] = (OMX_U8)((U1 + 2*U2 + U3 + 2)>>2);
289        pTmp[4] = (OMX_U8)((U2 + U3 + 1)>>1);
290        if (availability & OMX_VC_UPPER_RIGHT)
291        {
292            pTmp[5] = (OMX_U8)((U2 + 2*U3 + U4 + 2)>>2);
293            pTmp[6] = (OMX_U8)((U3 + U4 + 1)>>1);
294            pTmp[7] = (OMX_U8)((U3 + 2*U4 + U5 + 2)>>2);
295            pTmp[8] = (OMX_U8)((U4 + U5 + 1)>>1);
296            pTmp[9] = (OMX_U8)((U4 + 2*U5 + U6 + 2)>>2);
297        }
298        else
299        {
300            pTmp[5] = (OMX_U8)((U2 + 3*U3 + 2)>>2);
301            pTmp[6] = U3;
302            pTmp[7] = U3;
303            pTmp[8] = U3;
304            pTmp[9] = U3;
305        }
306        for (y=0; y<4; y++)
307        {
308            for (x=0; x<4; x++)
309            {
310                pDst[y*dstStep+x] = pTmp[2*x+y];
311            }
312        }
313        break;
314
315    case OMX_VC_4X4_HU:
316        /* zHU = x+2*y */
317        pTmp[0] = (OMX_U8)((L0 + L1 + 1)>>1);
318        pTmp[1] = (OMX_U8)((L0 + 2*L1 + L2 + 2)>>2);
319        pTmp[2] = (OMX_U8)((L1 + L2 + 1)>>1);
320        pTmp[3] = (OMX_U8)((L1 + 2*L2 + L3 + 2)>>2);
321        pTmp[4] = (OMX_U8)((L2 + L3 + 1)>>1);
322        pTmp[5] = (OMX_U8)((L2 + 3*L3 + 2)>>2);
323        pTmp[6] = L3;
324        pTmp[7] = L3;
325        pTmp[8] = L3;
326        pTmp[9] = L3;
327        for (y=0; y<4; y++)
328        {
329            for (x=0; x<4; x++)
330            {
331                pDst[y*dstStep+x] = pTmp[x+2*y];
332            }
333        }
334        break;
335    }
336
337    return OMX_Sts_NoErr;
338}
339