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_16x16.c
21 * OpenMAX DL: v1.0.2
22 * Revision:   9641
23 * Date:       Thursday, February 7, 2008
24 *
25 *
26 *
27 *
28 * H.264 16x16 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_16x16   (6.3.3.1.2)
41 *
42 * Description:
43 * Perform Intra_16x16 prediction for luma samples. If the upper-right block
44 * is not available, then duplication work should be handled inside the
45 * function. Users need not define them outside.
46 *
47 * Input Arguments:
48 *
49 *   pSrcLeft - Pointer to the buffer of 16 left pixels: p[x, y] (x = -1, y =
50 *            0..15)
51 *   pSrcAbove - Pointer to the buffer of 16 above pixels: p[x,y] (x = 0..15,
52 *            y= -1); must be aligned on a 16-byte boundary.
53 *   pSrcAboveLeft - Pointer to the above left pixels: p[x,y] (x = -1, y = -1)
54 *   leftStep - Step of left pixel buffer; must be a multiple of 16.
55 *   dstStep - Step of the destination buffer; must be a multiple of 16.
56 *   predMode - Intra_16x16 prediction mode, please refer to section 3.4.1.
57 *   availability - Neighboring 16x16 MB availability flag. Refer to
58 *                  section 3.4.4.
59 *
60 * Output Arguments:
61 *
62 *   pDst -Pointer to the destination buffer; must be aligned on a 16-byte
63 *            boundary.
64 *
65 * Return Value:
66 *    If the function runs without error, it returns OMX_Sts_NoErr.
67 *    If one of the following cases occurs, the function returns
68 *              OMX_Sts_BadArgErr:
69 *    pDst is NULL.
70 *    dstStep < 16. or dstStep is not a multiple of 16.
71 *    leftStep is not a multiple of 16.
72 *    predMode is not in the valid range of enumeration
73 *              OMXVCM4P10Intra16x16PredMode
74 *    predMode is OMX_VC_16X16_VERT, but availability doesn't set
75 *              OMX_VC_UPPER indicating p[x,-1] (x = 0..15) is not available.
76 *    predMode is OMX_VC_16X16_HOR, but availability doesn't set OMX_VC_LEFT
77 *              indicating p[-1,y] (y = 0..15) is not available.
78 *    predMode is OMX_VC_16X16_PLANE, but availability doesn't set
79 *              OMX_VC_UPPER_LEFT or OMX_VC_UPPER or OMX_VC_LEFT indicating
80 *              p[x,-1](x = 0..15), or p[-1,y] (y = 0..15), or p[-1,-1] is not
81 *              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 16-byte boundary.
86 *
87 * Note:
88 *     pSrcAbove, pSrcAbove, pSrcAboveLeft may be invalid pointers if
89 *     they are not used by intra prediction implied in predMode.
90 * Note:
91 *     OMX_VC_UPPER_RIGHT is not used in intra_16x16 luma prediction.
92 *
93 */
94OMXResult omxVCM4P10_PredictIntra_16x16(
95    const OMX_U8* pSrcLeft,
96    const OMX_U8 *pSrcAbove,
97    const OMX_U8 *pSrcAboveLeft,
98    OMX_U8* pDst,
99    OMX_INT leftStep,
100    OMX_INT dstStep,
101    OMXVCM4P10Intra16x16PredMode predMode,
102    OMX_S32 availability)
103{
104    int x,y,Sum,Count;
105    int H,V,a,b,c;
106
107    armRetArgErrIf(pDst == NULL, OMX_Sts_BadArgErr);
108    armRetArgErrIf(dstStep < 16,  OMX_Sts_BadArgErr);
109    armRetArgErrIf((dstStep % 16) != 0,  OMX_Sts_BadArgErr);
110    armRetArgErrIf((leftStep % 16) != 0,  OMX_Sts_BadArgErr);
111    armRetArgErrIf(armNot16ByteAligned(pSrcAbove), OMX_Sts_BadArgErr);
112    armRetArgErrIf(armNot16ByteAligned(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_16X16_VERT  && !(availability & OMX_VC_UPPER),      OMX_Sts_BadArgErr);
117    armRetArgErrIf(predMode==OMX_VC_16X16_HOR   && !(availability & OMX_VC_LEFT),       OMX_Sts_BadArgErr);
118    armRetArgErrIf(predMode==OMX_VC_16X16_PLANE && !(availability & OMX_VC_UPPER),      OMX_Sts_BadArgErr);
119    armRetArgErrIf(predMode==OMX_VC_16X16_PLANE && !(availability & OMX_VC_UPPER_LEFT), OMX_Sts_BadArgErr);
120    armRetArgErrIf(predMode==OMX_VC_16X16_PLANE && !(availability & OMX_VC_LEFT),       OMX_Sts_BadArgErr);
121    armRetArgErrIf((unsigned)predMode > OMX_VC_16X16_PLANE,  OMX_Sts_BadArgErr);
122
123    switch (predMode)
124    {
125    case OMX_VC_16X16_VERT:
126        for (y=0; y<16; y++)
127        {
128            for (x=0; x<16; x++)
129            {
130                pDst[y*dstStep+x] = pSrcAbove[x];
131            }
132        }
133        break;
134
135    case OMX_VC_16X16_HOR:
136        for (y=0; y<16; y++)
137        {
138            for (x=0; x<16; x++)
139            {
140                pDst[y*dstStep+x] = pSrcLeft[y*leftStep];
141            }
142        }
143        break;
144
145    case OMX_VC_16X16_DC:
146        /* This can always be used even if no blocks available */
147        Sum = 0;
148        Count = 0;
149        if (availability & OMX_VC_LEFT)
150        {
151            for (y=0; y<16; y++)
152            {
153                Sum += pSrcLeft[y*leftStep];
154            }
155            Count++;
156        }
157        if (availability & OMX_VC_UPPER)
158        {
159            for (x=0; x<16; x++)
160            {
161                Sum += pSrcAbove[x];
162            }
163            Count++;
164        }
165        if (Count==0)
166        {
167            Sum = 128;
168        }
169        else if (Count==1)
170        {
171            Sum = (Sum + 8) >> 4;
172        }
173        else /* Count = 2 */
174        {
175            Sum = (Sum + 16) >> 5;
176        }
177        for (y=0; y<16; y++)
178        {
179            for (x=0; x<16; x++)
180            {
181                pDst[y*dstStep+x] = (OMX_U8)Sum;
182            }
183        }
184        break;
185
186    case OMX_VC_16X16_PLANE:
187        H = 8*(pSrcAbove[15] - pSrcAboveLeft[0]);
188        for (x=6; x>=0; x--)
189        {
190            H += (x+1)*(pSrcAbove[8+x] - pSrcAbove[6-x]);
191        }
192        V = 8*(pSrcLeft[15*leftStep] - pSrcAboveLeft[0]);
193        for (y=6; y>=0; y--)
194        {
195            V += (y+1)*(pSrcLeft[(8+y)*leftStep] - pSrcLeft[(6-y)*leftStep]);
196        }
197        a = 16*(pSrcAbove[15] + pSrcLeft[15*leftStep]);
198        b = (5*H+32)>>6;
199        c = (5*V+32)>>6;
200        for (y=0; y<16; y++)
201        {
202            for (x=0; x<16; x++)
203            {
204                Sum = (a + b*(x-7) + c*(y-7) + 16)>>5;
205                pDst[y*dstStep+x] = (OMX_U8)armClip(0,255,Sum);
206            }
207        }
208        break;
209    }
210
211    return OMX_Sts_NoErr;
212}
213
214