1/*
2 * Copyright (C) 2009 The Android Open Source Project
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    Table of contents
20
21     1. Include headers
22     2. External compiler flags
23     3. Module defines
24     4. Local function prototypes
25     5. Functions
26          h264bsdProcessBlock
27          h264bsdProcessLumaDc
28          h264bsdProcessChromaDc
29
30------------------------------------------------------------------------------*/
31
32/*------------------------------------------------------------------------------
33    1. Include headers
34------------------------------------------------------------------------------*/
35
36#include "basetype.h"
37#include "h264bsd_transform.h"
38#include "h264bsd_util.h"
39
40/*------------------------------------------------------------------------------
41    2. External compiler flags
42--------------------------------------------------------------------------------
43
44--------------------------------------------------------------------------------
45    3. Module defines
46------------------------------------------------------------------------------*/
47
48/* Switch off the following Lint messages for this file:
49 * Info 701: Shift left of signed quantity (int)
50 * Info 702: Shift right of signed quantity (int)
51 */
52/*lint -e701 -e702 */
53
54/* LevelScale function */
55static const i32 levelScale[6][3] = {
56    {10,13,16}, {11,14,18}, {13,16,20}, {14,18,23}, {16,20,25}, {18,23,29}};
57
58/* qp % 6 as a function of qp */
59static const u8 qpMod6[52] = {0,1,2,3,4,5,0,1,2,3,4,5,0,1,2,3,4,5,0,1,2,3,4,5,
60    0,1,2,3,4,5,0,1,2,3,4,5,0,1,2,3,4,5,0,1,2,3,4,5,0,1,2,3};
61
62/* qp / 6 as a function of qp */
63static const u8 qpDiv6[52] = {0,0,0,0,0,0,1,1,1,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,
64    4,4,4,4,4,4,5,5,5,5,5,5,6,6,6,6,6,6,7,7,7,7,7,7,8,8,8,8};
65
66/*------------------------------------------------------------------------------
67    4. Local function prototypes
68------------------------------------------------------------------------------*/
69
70/*------------------------------------------------------------------------------
71
72    Function: h264bsdProcessBlock
73
74        Functional description:
75            Function performs inverse zig-zag scan, inverse scaling and
76            inverse transform for a luma or a chroma residual block
77
78        Inputs:
79            data            pointer to data to be processed
80            qp              quantization parameter
81            skip            skip processing of data[0], set to non-zero value
82                            if dc coeff hanled separately
83            coeffMap        16 lsb's indicate which coeffs are non-zero,
84                            bit 0 (lsb) for coeff 0, bit 1 for coeff 1 etc.
85
86        Outputs:
87            data            processed data
88
89        Returns:
90            HANTRO_OK       success
91            HANTRO_NOK      processed data not in valid range [-512, 511]
92
93------------------------------------------------------------------------------*/
94u32 h264bsdProcessBlock(i32 *data, u32 qp, u32 skip, u32 coeffMap)
95{
96
97/* Variables */
98
99    i32 tmp0, tmp1, tmp2, tmp3;
100    i32 d1, d2, d3;
101    u32 row,col;
102    u32 qpDiv;
103    i32 *ptr;
104
105/* Code */
106
107    qpDiv = qpDiv6[qp];
108    tmp1 = levelScale[qpMod6[qp]][0] << qpDiv;
109    tmp2 = levelScale[qpMod6[qp]][1] << qpDiv;
110    tmp3 = levelScale[qpMod6[qp]][2] << qpDiv;
111
112    if (!skip)
113        data[0] = (data[0] * tmp1);
114
115    /* at least one of the rows 1, 2 or 3 contain non-zero coeffs, mask takes
116     * the scanning order into account */
117    if (coeffMap & 0xFF9C)
118    {
119        /* do the zig-zag scan and inverse quantization */
120        d1 = data[1];
121        d2 = data[14];
122        d3 = data[15];
123        data[1] = (d1 * tmp2);
124        data[14] = (d2 * tmp2);
125        data[15] = (d3 * tmp3);
126
127        d1 = data[2];
128        d2 = data[5];
129        d3 = data[4];
130        data[4] = (d1 * tmp2);
131        data[2]  = (d2 * tmp1);
132        data[5] = (d3 * tmp3);
133
134        d1 = data[8];
135        d2 = data[3];
136        d3 = data[6];
137        tmp0 = (d1 * tmp2);
138        data[8] = (d2 * tmp1);
139        data[3]  = (d3 * tmp2);
140        d1 = data[7];
141        d2 = data[12];
142        d3 = data[9];
143        data[6]  = (d1 * tmp2);
144        data[7]  = (d2 * tmp3);
145        data[12] = (d3 * tmp2);
146        data[9]  = tmp0;
147
148        d1 = data[10];
149        d2 = data[11];
150        d3 = data[13];
151        data[13] = (d1 * tmp3);
152        data[10] = (d2 * tmp1);
153        data[11] = (d3 * tmp2);
154
155        /* horizontal transform */
156        for (row = 4, ptr = data; row--; ptr += 4)
157        {
158            tmp0 = ptr[0] + ptr[2];
159            tmp1 = ptr[0] - ptr[2];
160            tmp2 = (ptr[1] >> 1) - ptr[3];
161            tmp3 = ptr[1] + (ptr[3] >> 1);
162            ptr[0] = tmp0 + tmp3;
163            ptr[1] = tmp1 + tmp2;
164            ptr[2] = tmp1 - tmp2;
165            ptr[3] = tmp0 - tmp3;
166        }
167
168        /*lint +e661 +e662*/
169        /* then vertical transform */
170        for (col = 4; col--; data++)
171        {
172            tmp0 = data[0] + data[8];
173            tmp1 = data[0] - data[8];
174            tmp2 = (data[4] >> 1) - data[12];
175            tmp3 = data[4] + (data[12] >> 1);
176            data[0 ] = (tmp0 + tmp3 + 32)>>6;
177            data[4 ] = (tmp1 + tmp2 + 32)>>6;
178            data[8 ] = (tmp1 - tmp2 + 32)>>6;
179            data[12] = (tmp0 - tmp3 + 32)>>6;
180            /* check that each value is in the range [-512,511] */
181            if (((u32)(data[0] + 512) > 1023) ||
182                ((u32)(data[4] + 512) > 1023) ||
183                ((u32)(data[8] + 512) > 1023) ||
184                ((u32)(data[12] + 512) > 1023) )
185                return(HANTRO_NOK);
186        }
187    }
188    else /* rows 1, 2 and 3 are zero */
189    {
190        /* only dc-coeff is non-zero, i.e. coeffs at original positions
191         * 1, 5 and 6 are zero */
192        if ((coeffMap & 0x62) == 0)
193        {
194            tmp0 = (data[0] + 32) >> 6;
195            /* check that value is in the range [-512,511] */
196            if ((u32)(tmp0 + 512) > 1023)
197                return(HANTRO_NOK);
198            data[0] = data[1]  = data[2]  = data[3]  = data[4]  = data[5]  =
199                      data[6]  = data[7]  = data[8]  = data[9]  = data[10] =
200                      data[11] = data[12] = data[13] = data[14] = data[15] =
201                      tmp0;
202        }
203        else /* at least one of the coeffs 1, 5 or 6 is non-zero */
204        {
205            data[1] = (data[1] * tmp2);
206            data[2] = (data[5] * tmp1);
207            data[3] = (data[6] * tmp2);
208            tmp0 = data[0] + data[2];
209            tmp1 = data[0] - data[2];
210            tmp2 = (data[1] >> 1) - data[3];
211            tmp3 = data[1] + (data[3] >> 1);
212            data[0] = (tmp0 + tmp3 + 32)>>6;
213            data[1] = (tmp1 + tmp2 + 32)>>6;
214            data[2] = (tmp1 - tmp2 + 32)>>6;
215            data[3] = (tmp0 - tmp3 + 32)>>6;
216            data[4] = data[8] = data[12] = data[0];
217            data[5] = data[9] = data[13] = data[1];
218            data[6] = data[10] = data[14] = data[2];
219            data[7] = data[11] = data[15] = data[3];
220            /* check that each value is in the range [-512,511] */
221            if (((u32)(data[0] + 512) > 1023) ||
222                ((u32)(data[1] + 512) > 1023) ||
223                ((u32)(data[2] + 512) > 1023) ||
224                ((u32)(data[3] + 512) > 1023) )
225                return(HANTRO_NOK);
226        }
227    }
228
229    return(HANTRO_OK);
230
231}
232
233/*------------------------------------------------------------------------------
234
235    Function: h264bsdProcessLumaDc
236
237        Functional description:
238            Function performs inverse zig-zag scan, inverse transform and
239            inverse scaling for a luma DC coefficients block
240
241        Inputs:
242            data            pointer to data to be processed
243            qp              quantization parameter
244
245        Outputs:
246            data            processed data
247
248        Returns:
249            none
250
251------------------------------------------------------------------------------*/
252void h264bsdProcessLumaDc(i32 *data, u32 qp)
253{
254
255/* Variables */
256
257    i32 tmp0, tmp1, tmp2, tmp3;
258    u32 row,col;
259    u32 qpMod, qpDiv;
260    i32 levScale;
261    i32 *ptr;
262
263/* Code */
264
265    qpMod = qpMod6[qp];
266    qpDiv = qpDiv6[qp];
267
268    /* zig-zag scan */
269    tmp0 = data[2];
270    data[2]  = data[5];
271    data[5] = data[4];
272    data[4] = tmp0;
273
274    tmp0 = data[8];
275    data[8] = data[3];
276    data[3]  = data[6];
277    data[6]  = data[7];
278    data[7]  = data[12];
279    data[12] = data[9];
280    data[9]  = tmp0;
281
282    tmp0 = data[10];
283    data[10] = data[11];
284    data[11] = data[13];
285    data[13] = tmp0;
286
287    /* horizontal transform */
288    for (row = 4, ptr = data; row--; ptr += 4)
289    {
290        tmp0 = ptr[0] + ptr[2];
291        tmp1 = ptr[0] - ptr[2];
292        tmp2 = ptr[1] - ptr[3];
293        tmp3 = ptr[1] + ptr[3];
294        ptr[0] = tmp0 + tmp3;
295        ptr[1] = tmp1 + tmp2;
296        ptr[2] = tmp1 - tmp2;
297        ptr[3] = tmp0 - tmp3;
298    }
299
300    /*lint +e661 +e662*/
301    /* then vertical transform and inverse scaling */
302    levScale = levelScale[ qpMod ][0];
303    if (qp >= 12)
304    {
305        levScale <<= (qpDiv-2);
306        for (col = 4; col--; data++)
307        {
308            tmp0 = data[0] + data[8 ];
309            tmp1 = data[0] - data[8 ];
310            tmp2 = data[4] - data[12];
311            tmp3 = data[4] + data[12];
312            data[0 ] = ((tmp0 + tmp3)*levScale);
313            data[4 ] = ((tmp1 + tmp2)*levScale);
314            data[8 ] = ((tmp1 - tmp2)*levScale);
315            data[12] = ((tmp0 - tmp3)*levScale);
316        }
317    }
318    else
319    {
320        i32 tmp;
321        tmp = ((1 - qpDiv) == 0) ? 1 : 2;
322        for (col = 4; col--; data++)
323        {
324            tmp0 = data[0] + data[8 ];
325            tmp1 = data[0] - data[8 ];
326            tmp2 = data[4] - data[12];
327            tmp3 = data[4] + data[12];
328            data[0 ] = ((tmp0 + tmp3)*levScale+tmp) >> (2-qpDiv);
329            data[4 ] = ((tmp1 + tmp2)*levScale+tmp) >> (2-qpDiv);
330            data[8 ] = ((tmp1 - tmp2)*levScale+tmp) >> (2-qpDiv);
331            data[12] = ((tmp0 - tmp3)*levScale+tmp) >> (2-qpDiv);
332        }
333    }
334
335}
336
337/*------------------------------------------------------------------------------
338
339    Function: h264bsdProcessChromaDc
340
341        Functional description:
342            Function performs inverse transform and inverse scaling for a
343            chroma DC coefficients block
344
345        Inputs:
346            data            pointer to data to be processed
347            qp              quantization parameter
348
349        Outputs:
350            data            processed data
351
352        Returns:
353            none
354
355------------------------------------------------------------------------------*/
356void h264bsdProcessChromaDc(i32 *data, u32 qp)
357{
358
359/* Variables */
360
361    i32 tmp0, tmp1, tmp2, tmp3;
362    u32 qpDiv;
363    i32 levScale;
364    u32 levShift;
365
366/* Code */
367
368    qpDiv = qpDiv6[qp];
369    levScale = levelScale[ qpMod6[qp] ][0];
370
371    if (qp >= 6)
372    {
373        levScale <<= (qpDiv-1);
374        levShift = 0;
375    }
376    else
377    {
378        levShift = 1;
379    }
380
381    tmp0 = data[0] + data[2];
382    tmp1 = data[0] - data[2];
383    tmp2 = data[1] - data[3];
384    tmp3 = data[1] + data[3];
385    data[0] = ((tmp0 + tmp3) * levScale) >> levShift;
386    data[1] = ((tmp0 - tmp3) * levScale) >> levShift;
387    data[2] = ((tmp1 + tmp2) * levScale) >> levShift;
388    data[3] = ((tmp1 - tmp2) * levScale) >> levShift;
389    tmp0 = data[4] + data[6];
390    tmp1 = data[4] - data[6];
391    tmp2 = data[5] - data[7];
392    tmp3 = data[5] + data[7];
393    data[4] = ((tmp0 + tmp3) * levScale) >> levShift;
394    data[5] = ((tmp0 - tmp3) * levScale) >> levShift;
395    data[6] = ((tmp1 + tmp2) * levScale) >> levShift;
396    data[7] = ((tmp1 - tmp2) * levScale) >> levShift;
397
398}
399
400/*lint +e701 +e702 */
401
402
403