1/******************************************************************************
2*
3* Copyright (C) 2012 Ittiam Systems Pvt Ltd, Bangalore
4*
5* Licensed under the Apache License, Version 2.0 (the "License");
6* you may not use this file except in compliance with the License.
7* You may obtain a copy of the License at:
8*
9* http://www.apache.org/licenses/LICENSE-2.0
10*
11* Unless required by applicable law or agreed to in writing, software
12* distributed under the License is distributed on an "AS IS" BASIS,
13* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14* See the License for the specific language governing permissions and
15* limitations under the License.
16*
17******************************************************************************/
18/**
19 *******************************************************************************
20 * @file
21 *  ihevc_chroma_iquant_itrans_recon.c
22 *
23 * @brief
24 *  Contains function definitions for inverse  quantization, inverse
25 * transform and reconstruction  of chroma interleaved data.
26 *
27 * @author
28 *  100470
29 *
30 * @par List of Functions:
31 *   - ihevc_chroma_iquant_itrans_recon_4x4()
32 *
33 * @remarks
34 *  None
35 *
36 *******************************************************************************
37 */
38#include <stdio.h>
39#include <string.h>
40#include "ihevc_typedefs.h"
41#include "ihevc_macros.h"
42#include "ihevc_platform_macros.h"
43#include "ihevc_defs.h"
44#include "ihevc_trans_tables.h"
45#include "ihevc_chroma_iquant_itrans_recon.h"
46#include "ihevc_func_selector.h"
47#include "ihevc_trans_macros.h"
48
49/* All the functions work one component(U or V) of interleaved data depending upon pointers passed to it */
50/* Data visualization */
51/* U V U V U V U V */
52/* U V U V U V U V */
53/* U V U V U V U V */
54/* U V U V U V U V */
55/* If the pointer points to first byte of above stream (U) , functions will operate on U component */
56/* If the pointer points to second byte of above stream (V) , functions will operate on V component */
57
58
59/**
60 *******************************************************************************
61 *
62 * @brief
63 *  This function performs inverse quantization, inverse  transform and
64 * reconstruction for 4x4 input block
65 *
66 * @par Description:
67 *  Performs inverse quantization , inverse transform  and adds the
68 * prediction data and clips output to 8 bit
69 *
70 * @param[in] pi2_src
71 *  Input 4x4 coefficients
72 *
73 * @param[in] pi2_tmp
74 *  Temporary 4x4 buffer for storing inverse transform
75 *  1st stage output
76 *
77 * @param[in] pu1_pred
78 *  Prediction 4x4 block
79 *
80 * @param[in] pi2_dequant_coeff
81 *  Dequant Coeffs
82 *
83 * @param[out] pu1_dst
84 *  Output 4x4 block
85 *
86 * @param[in] qp_div
87 *  Quantization parameter / 6
88 *
89 * @param[in] qp_rem
90 *  Quantization parameter % 6
91 *
92 * @param[in] src_strd
93 *  Input stride
94 *
95 * @param[in] pred_strd
96 *  Prediction stride
97 *
98 * @param[in] dst_strd
99 *  Output Stride
100 *
101 * @param[in] zero_cols
102 *  Zero columns in pi2_src
103 *
104 * @param[in] zero_rows
105 *  Zero Rows in pi2_src
106 *
107 * @returns  Void
108 *
109 * @remarks
110 *  None
111 *
112 *******************************************************************************
113 */
114
115
116void ihevc_chroma_iquant_itrans_recon_4x4(WORD16 *pi2_src,
117                                          WORD16 *pi2_tmp,
118                                          UWORD8 *pu1_pred,
119                                          WORD16 *pi2_dequant_coeff,
120                                          UWORD8 *pu1_dst,
121                                          WORD32 qp_div, /* qpscaled / 6 */
122                                          WORD32 qp_rem, /* qpscaled % 6 */
123                                          WORD32 src_strd,
124                                          WORD32 pred_strd,
125                                          WORD32 dst_strd,
126                                          WORD32 zero_cols,
127                                          WORD32 zero_rows)
128{
129    UNUSED(zero_rows);
130
131    /* Inverse Transform */
132    {
133        WORD32 j;
134        WORD32 e[2], o[2];
135        WORD32 add;
136        WORD32 shift;
137        WORD16 *pi2_tmp_orig;
138        WORD32 shift_iq;
139        WORD32 trans_size;
140        /* Inverse Quantization constants */
141        {
142            WORD32 log2_trans_size, bit_depth;
143
144            log2_trans_size = 2;
145            bit_depth = 8 + 0;
146            shift_iq = bit_depth + log2_trans_size - 5;
147        }
148
149        trans_size = TRANS_SIZE_4;
150        pi2_tmp_orig = pi2_tmp;
151
152        /* Inverse Transform 1st stage */
153        shift = IT_SHIFT_STAGE_1;
154        add = 1 << (shift - 1);
155
156        for(j = 0; j < trans_size; j++)
157        {
158            /* Checking for Zero Cols */
159            if((zero_cols & 1) == 1)
160            {
161                memset(pi2_tmp, 0, trans_size * sizeof(WORD16));
162            }
163            else
164            {
165                WORD32 iq_tmp_1, iq_tmp_2;
166                /* Utilizing symmetry properties to the maximum to minimize the number of multiplications */
167                IQUANT_4x4(iq_tmp_1,
168                           pi2_src[1 * src_strd],
169                           pi2_dequant_coeff[1 * trans_size] * g_ihevc_iquant_scales[qp_rem],
170                           shift_iq, qp_div);
171                IQUANT_4x4(iq_tmp_2,
172                           pi2_src[3 * src_strd],
173                           pi2_dequant_coeff[3 * trans_size] * g_ihevc_iquant_scales[qp_rem],
174                           shift_iq, qp_div);
175
176                o[0] = g_ai2_ihevc_trans_4[1][0] * iq_tmp_1
177                                + g_ai2_ihevc_trans_4[3][0] * iq_tmp_2;
178                o[1] = g_ai2_ihevc_trans_4[1][1] * iq_tmp_1
179                                + g_ai2_ihevc_trans_4[3][1] * iq_tmp_2;
180
181                IQUANT_4x4(iq_tmp_1,
182                           pi2_src[0 * src_strd],
183                           pi2_dequant_coeff[0 * trans_size] * g_ihevc_iquant_scales[qp_rem],
184                           shift_iq, qp_div);
185                IQUANT_4x4(iq_tmp_2,
186                           pi2_src[2 * src_strd],
187                           pi2_dequant_coeff[2 * trans_size] * g_ihevc_iquant_scales[qp_rem],
188                           shift_iq, qp_div);
189
190                e[0] = g_ai2_ihevc_trans_4[0][0] * iq_tmp_1
191                                + g_ai2_ihevc_trans_4[2][0] * iq_tmp_2;
192                e[1] = g_ai2_ihevc_trans_4[0][1] * iq_tmp_1
193                                + g_ai2_ihevc_trans_4[2][1] * iq_tmp_2;
194
195                pi2_tmp[0] =
196                                CLIP_S16(((e[0] + o[0] + add) >> shift));
197                pi2_tmp[1] =
198                                CLIP_S16(((e[1] + o[1] + add) >> shift));
199                pi2_tmp[2] =
200                                CLIP_S16(((e[1] - o[1] + add) >> shift));
201                pi2_tmp[3] =
202                                CLIP_S16(((e[0] - o[0] + add) >> shift));
203            }
204            pi2_src++;
205            pi2_dequant_coeff++;
206            pi2_tmp += trans_size;
207            zero_cols = zero_cols >> 1;
208        }
209
210        pi2_tmp = pi2_tmp_orig;
211
212        /* Inverse Transform 2nd stage */
213        shift = IT_SHIFT_STAGE_2;
214        add = 1 << (shift - 1);
215
216        for(j = 0; j < trans_size; j++)
217        {
218            WORD32 itrans_out;
219
220            /* Utilizing symmetry properties to the maximum to minimize the number of multiplications */
221            o[0] = g_ai2_ihevc_trans_4[1][0] * pi2_tmp[trans_size]
222                            + g_ai2_ihevc_trans_4[3][0]
223                                            * pi2_tmp[3 * trans_size];
224            o[1] = g_ai2_ihevc_trans_4[1][1] * pi2_tmp[trans_size]
225                            + g_ai2_ihevc_trans_4[3][1]
226                                            * pi2_tmp[3 * trans_size];
227            e[0] = g_ai2_ihevc_trans_4[0][0] * pi2_tmp[0]
228                            + g_ai2_ihevc_trans_4[2][0]
229                                            * pi2_tmp[2 * trans_size];
230            e[1] = g_ai2_ihevc_trans_4[0][1] * pi2_tmp[0]
231                            + g_ai2_ihevc_trans_4[2][1]
232                                            * pi2_tmp[2 * trans_size];
233
234            itrans_out =
235                            CLIP_S16(((e[0] + o[0] + add) >> shift));
236            pu1_dst[0 * 2] = CLIP_U8((itrans_out + pu1_pred[0 * 2]));
237
238            itrans_out =
239                            CLIP_S16(((e[1] + o[1] + add) >> shift));
240            pu1_dst[1 * 2] = CLIP_U8((itrans_out + pu1_pred[1 * 2]));
241
242            itrans_out =
243                            CLIP_S16(((e[1] - o[1] + add) >> shift));
244            pu1_dst[2 * 2] = CLIP_U8((itrans_out + pu1_pred[2 * 2]));
245
246            itrans_out =
247                            CLIP_S16(((e[0] - o[0] + add) >> shift));
248            pu1_dst[3 * 2] = CLIP_U8((itrans_out + pu1_pred[3 * 2]));
249
250            pi2_tmp++;
251            pu1_pred += pred_strd;
252            pu1_dst += dst_strd;
253
254        }
255    }
256}
257