• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Samsung Electronics Co., Ltd.
3  * All Rights Reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * - Redistributions of source code must retain the above copyright notice,
9  *   this list of conditions and the following disclaimer.
10  *
11  * - Redistributions in binary form must reproduce the above copyright notice,
12  *   this list of conditions and the following disclaimer in the documentation
13  *   and/or other materials provided with the distribution.
14  *
15  * - Neither the name of the copyright owner, nor the names of its contributors
16  *   may be used to endorse or promote products derived from this software
17  *   without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include "oapv_tq.h"
33 #include <math.h>
34 
35 ///////////////////////////////////////////////////////////////////////////////
36 // start of encoder code
37 #if ENABLE_ENCODER
38 ///////////////////////////////////////////////////////////////////////////////
39 
40 const int   oapv_quant_scale[6] = { 26214, 23302, 20560, 18396, 16384, 14769 };
41 
oapv_tx_part(s16 * src,s16 * dst,int shift,int line)42 static void oapv_tx_part(s16 *src, s16 *dst, int shift, int line)
43 {
44     int j, k;
45     int E[4], O[4];
46     int EE[2], EO[2];
47     int add = 1 << (shift - 1);
48 
49     for(j = 0; j < line; j++) {
50         /* E and O*/
51         for(k = 0; k < 4; k++) {
52             E[k] = src[j * 8 + k] + src[j * 8 + 7 - k];
53             O[k] = src[j * 8 + k] - src[j * 8 + 7 - k];
54         }
55         /* EE and EO */
56         EE[0] = E[0] + E[3];
57         EO[0] = E[0] - E[3];
58         EE[1] = E[1] + E[2];
59         EO[1] = E[1] - E[2];
60 
61         dst[0 * line + j] = (oapv_tbl_tm8[0][0] * EE[0] + oapv_tbl_tm8[0][1] * EE[1] + add) >> shift;
62         dst[4 * line + j] = (oapv_tbl_tm8[4][0] * EE[0] + oapv_tbl_tm8[4][1] * EE[1] + add) >> shift;
63         dst[2 * line + j] = (oapv_tbl_tm8[2][0] * EO[0] + oapv_tbl_tm8[2][1] * EO[1] + add) >> shift;
64         dst[6 * line + j] = (oapv_tbl_tm8[6][0] * EO[0] + oapv_tbl_tm8[6][1] * EO[1] + add) >> shift;
65 
66         dst[1 * line + j] = (oapv_tbl_tm8[1][0] * O[0] + oapv_tbl_tm8[1][1] * O[1] + oapv_tbl_tm8[1][2] * O[2] + oapv_tbl_tm8[1][3] * O[3] + add) >> shift;
67         dst[3 * line + j] = (oapv_tbl_tm8[3][0] * O[0] + oapv_tbl_tm8[3][1] * O[1] + oapv_tbl_tm8[3][2] * O[2] + oapv_tbl_tm8[3][3] * O[3] + add) >> shift;
68         dst[5 * line + j] = (oapv_tbl_tm8[5][0] * O[0] + oapv_tbl_tm8[5][1] * O[1] + oapv_tbl_tm8[5][2] * O[2] + oapv_tbl_tm8[5][3] * O[3] + add) >> shift;
69         dst[7 * line + j] = (oapv_tbl_tm8[7][0] * O[0] + oapv_tbl_tm8[7][1] * O[1] + oapv_tbl_tm8[7][2] * O[2] + oapv_tbl_tm8[7][3] * O[3] + add) >> shift;
70     }
71 }
72 
73 const oapv_fn_tx_t oapv_tbl_fn_tx[2] = {
74     oapv_tx_part,
75     NULL
76 };
77 
get_transform_shift(int log2_size,int type,int bit_depth)78 static __inline int get_transform_shift(int log2_size, int type, int bit_depth)
79 {
80     if(type == 0) {
81         return ((log2_size)-1 + bit_depth - 8);
82     }
83     else {
84         return ((log2_size) + 6);
85     }
86 }
87 
oapv_trans(oapve_ctx_t * ctx,s16 * coef,int log2_w,int log2_h,int bit_depth)88 void oapv_trans(oapve_ctx_t *ctx, s16 *coef, int log2_w, int log2_h, int bit_depth)
89 {
90     int shift1 = get_transform_shift(log2_w, 0, bit_depth);
91     int shift2 = get_transform_shift(log2_h, 1, bit_depth);
92 
93     ALIGNED_16(s16 tb[OAPV_BLK_D]);
94     (ctx->fn_txb)[0](coef, tb, shift1, 1 << log2_h);
95     (ctx->fn_txb)[0](tb, coef, shift2, 1 << log2_w);
96 }
97 
oapv_quant(s16 * coef,u8 qp,int q_matrix[OAPV_BLK_D],int log2_w,int log2_h,int bit_depth,int deadzone_offset)98 static int oapv_quant(s16 *coef, u8 qp, int q_matrix[OAPV_BLK_D], int log2_w, int log2_h, int bit_depth, int deadzone_offset)
99 {
100     // coef is the output of the transform, the bit range is 16
101     // q_matrix has the value of q_scale * 16 / q_matrix, the bit range is 19
102     // (precision of q_scale is 15, and the range of q_mtrix is 1~255)
103     // lev is the product of abs(coef) and q_matrix, the bit range is 35
104 
105     s64 lev;
106     s32 offset;
107     int sign;
108     int i;
109     int shift;
110     int tr_shift;
111     int log2_size = (log2_w + log2_h) >> 1;
112 
113     tr_shift = MAX_TX_DYNAMIC_RANGE - bit_depth - log2_size;
114     shift = QUANT_SHIFT + tr_shift + (qp / 6);
115     offset = deadzone_offset << (shift - 9);
116     int pixels = (1 << (log2_w + log2_h));
117 
118     for(i = 0; i < pixels; i++) {
119         sign = oapv_get_sign(coef[i]);
120         lev = (s64)oapv_abs(coef[i]) * (q_matrix[i]);
121         lev = (lev + offset) >> shift;
122         lev = oapv_set_sign(lev, sign);
123         coef[i] = (s16)(oapv_clip3(-32768, 32767, lev));
124     }
125     return OAPV_OK;
126 }
127 
128 const oapv_fn_quant_t oapv_tbl_fn_quant[2] = {
129     oapv_quant,
130     NULL
131 };
132 
133 ///////////////////////////////////////////////////////////////////////////////
134 // end of encoder code
135 #endif // ENABLE_ENCODER
136 ///////////////////////////////////////////////////////////////////////////////
137 
oapv_itx_get_wo_sft(s16 * src,s16 * dst,s32 * dst32,int shift,int line)138 void oapv_itx_get_wo_sft(s16 *src, s16 *dst, s32 *dst32, int shift, int line)
139 {
140     int j, k;
141     s32 E[4], O[4];
142     s32 EE[2], EO[2];
143     int add = 1 << (shift - 1);
144 
145     for(j = 0; j < line; j++) {
146         /* Utilizing symmetry properties to the maximum to minimize the number of multiplications */
147         for(k = 0; k < 4; k++) {
148             O[k] = oapv_tbl_tm8[1][k] * src[1 * line + j] + oapv_tbl_tm8[3][k] * src[3 * line + j] + oapv_tbl_tm8[5][k] * src[5 * line + j] + oapv_tbl_tm8[7][k] * src[7 * line + j];
149         }
150 
151         EO[0] = oapv_tbl_tm8[2][0] * src[2 * line + j] + oapv_tbl_tm8[6][0] * src[6 * line + j];
152         EO[1] = oapv_tbl_tm8[2][1] * src[2 * line + j] + oapv_tbl_tm8[6][1] * src[6 * line + j];
153         EE[0] = oapv_tbl_tm8[0][0] * src[0 * line + j] + oapv_tbl_tm8[4][0] * src[4 * line + j];
154         EE[1] = oapv_tbl_tm8[0][1] * src[0 * line + j] + oapv_tbl_tm8[4][1] * src[4 * line + j];
155 
156         /* Combining even and odd terms at each hierarchy levels to calculate the final spatial domain vector */
157         E[0] = EE[0] + EO[0];
158         E[3] = EE[0] - EO[0];
159         E[1] = EE[1] + EO[1];
160         E[2] = EE[1] - EO[1];
161 
162         for(k = 0; k < 4; k++) {
163             dst32[j * 8 + k] = E[k] + O[k];
164             dst32[j * 8 + k + 4] = E[3 - k] - O[3 - k];
165 
166             dst[j * 8 + k] = ((dst32[j * 8 + k] + add) >> shift);
167             dst[j * 8 + k + 4] = ((dst32[j * 8 + k + 4] + add) >> shift);
168         }
169     }
170 }
171 
oapv_itx_part(s16 * src,s16 * dst,int shift,int line)172 static void oapv_itx_part(s16 *src, s16 *dst, int shift, int line)
173 {
174     int j, k;
175     int E[4], O[4];
176     int EE[2], EO[2];
177     int add = 1 << (shift - 1);
178 
179     for(j = 0; j < line; j++) {
180         /* Utilizing symmetry properties to the maximum to minimize the number of multiplications */
181         for(k = 0; k < 4; k++) {
182             O[k] = oapv_tbl_tm8[1][k] * src[1 * line + j] + oapv_tbl_tm8[3][k] * src[3 * line + j] + oapv_tbl_tm8[5][k] * src[5 * line + j] + oapv_tbl_tm8[7][k] * src[7 * line + j];
183         }
184 
185         EO[0] = oapv_tbl_tm8[2][0] * src[2 * line + j] + oapv_tbl_tm8[6][0] * src[6 * line + j];
186         EO[1] = oapv_tbl_tm8[2][1] * src[2 * line + j] + oapv_tbl_tm8[6][1] * src[6 * line + j];
187         EE[0] = oapv_tbl_tm8[0][0] * src[0 * line + j] + oapv_tbl_tm8[4][0] * src[4 * line + j];
188         EE[1] = oapv_tbl_tm8[0][1] * src[0 * line + j] + oapv_tbl_tm8[4][1] * src[4 * line + j];
189 
190         /* Combining even and odd terms at each hierarchy levels to calculate the final spatial domain vector */
191         E[0] = EE[0] + EO[0];
192         E[3] = EE[0] - EO[0];
193         E[1] = EE[1] + EO[1];
194         E[2] = EE[1] - EO[1];
195 
196         for(k = 0; k < 4; k++) {
197             dst[j * 8 + k] = ((E[k] + O[k] + add) >> shift);
198             dst[j * 8 + k + 4] = ((E[3 - k] - O[3 - k] + add) >> shift);
199         }
200     }
201 }
202 
203 const oapv_fn_itx_part_t oapv_tbl_fn_itx_part[2] = {
204     oapv_itx_part,
205     NULL
206 };
207 
oapv_itx(s16 * src,int shift1,int shift2,int line)208 static void oapv_itx(s16 *src, int shift1, int shift2, int line)
209 {
210     ALIGNED_16(s16 dst[OAPV_BLK_D]);
211     oapv_itx_part(src, dst, shift1, line);
212     oapv_itx_part(dst, src, shift2, line);
213 }
214 
215 const oapv_fn_itx_t oapv_tbl_fn_itx[2] = {
216     oapv_itx,
217     NULL
218 };
219 
oapv_dquant(s16 * coef,s16 q_matrix[OAPV_BLK_D],int log2_w,int log2_h,s8 shift)220 static void oapv_dquant(s16 *coef, s16 q_matrix[OAPV_BLK_D], int log2_w, int log2_h, s8 shift)
221 {
222     int i;
223     int lev;
224     int pixels = (1 << (log2_w + log2_h));
225 
226     if(shift > 0) {
227         s32 offset = (1 << (shift - 1));
228         for(i = 0; i < pixels; i++) {
229             lev = (coef[i] * q_matrix[i] + offset) >> shift;
230             coef[i] = (s16)oapv_clip3(-32768, 32767, lev);
231         }
232     }
233     else {
234         int left_shift = -shift;
235         for(i = 0; i < pixels; i++) {
236             lev = (coef[i] * q_matrix[i]) << left_shift;
237             coef[i] = (s16)oapv_clip3(-32768, 32767, lev);
238         }
239     }
240 }
241 
242 const oapv_fn_dquant_t oapv_tbl_fn_dquant[2] = {
243     oapv_dquant,
244     NULL
245 };
246 
oapv_adjust_itrans(int * src,int * dst,int itrans_diff_idx,int diff_step,int shift)247 void oapv_adjust_itrans(int *src, int *dst, int itrans_diff_idx, int diff_step, int shift)
248 {
249     int offset = 1 << (shift - 1);
250     for(int k = 0; k < 64; k++) {
251         dst[k] = src[k] + ((oapv_itrans_diff[itrans_diff_idx][k] * diff_step + offset) >> shift);
252     }
253 }
254 
255 const oapv_fn_itx_adj_t oapv_tbl_fn_itx_adj[2] = {
256     oapv_adjust_itrans,
257     NULL,
258 };
259