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