1 /*
2 * Copyright (C) 2021 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19 #ifndef __HI_MATH_H__
20 #define __HI_MATH_H__
21
22 #include "hi_type.h"
23
24 #ifdef __cplusplus
25 #if __cplusplus
26 extern "C" {
27 #endif
28 #endif /* __cplusplus */
29
30 /*
31 * ABS(x) absolute value of x
32 * SIGN(x) sign of x
33 * CMP(x,y) 0 if x == y; 1 if x > y; -1 if x < y
34 */
35 #define ABS(x) ((x) >= 0 ? (x) : (-(x)))
36 #define _SIGN(x) ((x) >= 0 ? 1 : (-1))
37 #define CMP(x, y) (((x) == (y)) ? 0 : (((x) > (y)) ? 1 : (-1)))
38
39 /*
40 * MAX2(x,y) maximum of x and y
41 * MIN2(x,y) minimum of x and y
42 * MAX3(x,y,z) maximum of x, y and z
43 * MIN3(x,y,z) minimum of x, y and z
44 * MEDIAN(x,y,z) median of x,y,z
45 * MEAN2(x,y) mean of x,y
46 */
47 #define MAX2(x, y) ((x) > (y) ? (x) : (y))
48 #define MIN2(x, y) ((x) < (y) ? (x) : (y))
49 #define MAX3(x, y, z) ((x) > (y) ? MAX2(x, z) : MAX2(y, z))
50 #define MIN3(x, y, z) ((x) < (y) ? MIN2(x, z) : MIN2(y, z))
51 #define MEDIAN(x, y, z) (((x) + (y) + (z) - MAX3(x, y, z)) - MIN3(x, y, z))
52 #define MEAN2(x, y) (((x) + (y)) >> 1)
53
54 /*
55 * CLIP3(x,min,max) clip x within [min,max]
56 * WRAP_MAX(x,max,min) wrap to min if x equal max
57 * WRAP_MIN(x,min,max) wrap to max if x equal min
58 * VALUE_BETWEEN(x,min.max) True if x is between [min,max] inclusively.
59 */
60 #define CLIP_MIN(x, min) (((x) >= (min)) ? (x) : (min))
61 #define CLIP3(x, min, max) ((x) < (min) ? (min) : ((x) > (max) ? (max) :(x)))
62 #define CLIP_MAX(x, max) ((x) > (max) ? (max) : (x))
63 #define WRAP_MAX(x, max, min) ((x) >= (max) ? (min) : (x))
64 #define WRAP_MIN(x, min, max) ((x) <= (min) ? (max) : (x))
65 #define VALUE_BETWEEN(x, min, max) (((x) >= (min)) && ((x) <= (max)))
66
67 /*
68 * MULTI_OF_2_POWER(x,a) whether x is multiple of a(a must be power of 2)
69 * HI_ALIGN_DOWN(x,a) floor x to multiple of a(a must be power of 2)
70 * HI_ALIGN_UP(x, a) align x to multiple of a
71 *
72 * Example:
73 * HI_ALIGN_UP(5,4) = 8
74 * HI_ALIGN_DOWN(5,4) = 4
75 */
76 #define MULTI_OF_2_POWER(x, a) (!((x) & ((a) - 1)))
77 #define HICEILING(x, a) (((x) + (a) - 1) / (a))
78
79 #define HI_ALIGN_UP(x, a) ((((x) + ((a) - 1)) / (a)) * (a))
80 #define HI_ALIGN_DOWN(x, a) (((x) / (a)) * (a))
81 #define ALIGN_UP(x, a) ((((x) + ((a) - 1)) / (a)) * (a))
82 #define ALIGN_DOWN(x, a) (((x) / (a)) * (a))
83
84 #define DIV_UP(x, a) (((x) + ((a) - 1)) / (a))
85
86 /*
87 * Get the span between two unsigned number, such as
88 * SPAN(HI_U32, 200, 100) is 200 - 100 = 100
89 * SPAN(HI_U32, 100, 200) is 0xFFFFFFFF - 200 + 100
90 * SPAN(HI_U64, 100, 200) is 0xFFFFFFFFFFFFFFFF - 200 + 100
91 */
92 #define SPAN(type, begin, end) \
93 ({ \
94 type b = (begin); \
95 type e = (end); \
96 (type)((b >= e) ? (b - e) : (b + ((~((type)0)) - e))); \
97 })
98
99 /*
100 * ENDIAN32(x,y) little endian <---> big endian
101 * IS_LITTLE_END() whether the system is little end mode
102 */
103 #define ENDIAN32(x) \
104 (((x) << 24) | \
105 (((x) & 0x0000ff00) << 8) | \
106 (((x) & 0x00ff0000) >> 8) | \
107 (((x) >> 24) & 0x000000ff))
108
109 /*
110 * ENDIAN16(x,y) little endian <---> big endian
111 * IS_LITTLE_END() whether the system is little end mode
112 */
113 #define ENDIAN16(x) ((((x) << 8) & 0xff00) | (((x) >> 8) & 255))
114
IS_LITTLE_END(void)115 __inline static HI_BOOL IS_LITTLE_END(void)
116 {
117 union unEND_TEST_U {
118 HI_CHAR cTest[4];
119 HI_U32 u32Test;
120 } unEndTest;
121
122 unEndTest.cTest[0] = 0x01;
123 unEndTest.cTest[1] = 0x02;
124 unEndTest.cTest[2] = 0x03;
125 unEndTest.cTest[3] = 0x04;
126
127 return (unEndTest.u32Test > 0x01020304) ? (HI_TRUE) : (HI_FALSE);
128 }
129
130 /*
131 * FRACTION32(de,nu) fraction: nu(minator) / de(nominator).
132 * NUMERATOR32(x) of x(x is fraction)
133 * DENOMINATOR32(x) Denominator of x(x is fraction)
134
135 * represent fraction in 32 bit. LSB 16 is numerator, MSB 16 is denominator
136 * It is integer if denominator is 0.
137 */
138 #define FRACTION32(de, nu) (((de) << 16) | (nu))
139 #define NUMERATOR32(x) ((x) & 0xffff)
140 #define DENOMINATOR32(x) ((x) >> 16)
141
142 /*
143 * RGB(r,g,b) assemble the r,g,b to 24bit color
144 * RGB_R(c) get RED from 24bit color
145 * RGB_G(c) get GREEN from 24bit color
146 * RGB_B(c) get BLUE from 24bit color
147 */
148 #define RGB(r, g, b) ((((r) & 0xff) << 16) | (((g) & 0xff) << 8) | ((b) & 0xff))
149 #define RGB_R(c) (((c) & 0xff0000) >> 16)
150 #define RGB_G(c) (((c) & 0xff00) >> 8)
151 #define RGB_B(c) ((c) & 0xff)
152
153 /*
154 * YUV(y,u,v) assemble the y,u,v to 30bit color
155 * YUV_Y(c) get Y from 30bit color
156 * YUV_U(c) get U from 30bit color
157 * YUV_V(c) get V from 30bit color
158 */
159 #define YUV(y, u, v) ((((y) & 0x03ff) << 20) | (((u) & 0x03ff) << 10) | ((v) & 0x03ff))
160 #define YUV_Y(c) (((c) & 0x3ff00000) >> 20)
161 #define YUV_U(c) (((c) & 0x000ffc00) >> 10)
162 #define YUV_V(c) ((c) & 0x000003ff)
163
164 /*
165 * YUV_8BIT(y,u,v) assemble the y,u,v to 24bit color
166 * YUV_8BIT_Y(c) get Y from 24bit color
167 * YUV_8BIT_U(c) get U from 24bit color
168 * YUV_8BIT_V(c) get V from 24bit color
169 */
170 #define YUV_8BIT(y, u, v) ((((y) & 0xff) << 16) | (((u) & 0xff) << 8) | ((v) & 0xff))
171 #define YUV_8BIT_Y(c) (((c) & 0xff0000) >> 16)
172 #define YUV_8BIT_U(c) (((c) & 0xff00) >> 8)
173 #define YUV_8BIT_V(c) ((c) & 0xff)
174
175 /*
176 * Rgb2Yc(r, g, b, *y, *u, *u) convert r,g,b to y,u,v
177 * Rgb2Yuv(rgb) convert rgb to yuv
178 */
Rgb2Yc(HI_U16 r, HI_U16 g, HI_U16 b, HI_U16 *py, HI_U16 *pcb, HI_U16 *pcr)179 __inline static HI_VOID Rgb2Yc(HI_U16 r, HI_U16 g, HI_U16 b, HI_U16 *py, HI_U16 *pcb, HI_U16 *pcr)
180 {
181 /* Y */
182 *py = (HI_U16)((((r * 66 + g * 129 + b * 25) >> 8) + 16) << 2);
183
184 /* Cb */
185 *pcb = (HI_U16)(((((b * 112 - r * 38) - g * 74) >> 8) + 128) << 2);
186
187 /* Cr */
188 *pcr = (HI_U16)(((((r * 112 - g * 94) - b * 18) >> 8) + 128) << 2);
189 }
190
Rgb2Yuv(HI_U32 u32Rgb)191 __inline static HI_U32 Rgb2Yuv(HI_U32 u32Rgb)
192 {
193 HI_U16 y, u, v;
194
195 Rgb2Yc(RGB_R(u32Rgb), RGB_G(u32Rgb), RGB_B(u32Rgb), &y, &u, &v);
196
197 return YUV(y, u, v);
198 }
199
Rgb2Yc_full(HI_U16 r, HI_U16 g, HI_U16 b, HI_U16 *py, HI_U16 *pcb, HI_U16 *pcr)200 __inline static HI_VOID Rgb2Yc_full(HI_U16 r, HI_U16 g, HI_U16 b, HI_U16 *py, HI_U16 *pcb, HI_U16 *pcr)
201 {
202 HI_U16 py_temp, pcb_temp, pcr_temp;
203
204 py_temp = (HI_U16)(((r * 76 + g * 150 + b * 29) >> 8) * 4);
205 pcb_temp = (HI_U16)(CLIP_MIN(((((b * 130 - r * 44) - g * 86) >> 8) + 128), 0) * 4);
206 pcr_temp = (HI_U16)(CLIP_MIN(((((r * 130 - g * 109) - b * 21) >> 8) + 128), 0) * 4);
207
208 *py = MAX2(MIN2(py_temp, 1023), 0);
209 *pcb = MAX2(MIN2(pcb_temp, 1023), 0);
210 *pcr = MAX2(MIN2(pcr_temp, 1023), 0);
211 }
212
Rgb2Yuv_full(HI_U32 u32Rgb)213 __inline static HI_U32 Rgb2Yuv_full(HI_U32 u32Rgb)
214 {
215 HI_U16 y, u, v;
216
217 Rgb2Yc_full(RGB_R(u32Rgb), RGB_G(u32Rgb), RGB_B(u32Rgb), &y, &u, &v);
218
219 return YUV(y, u, v);
220 }
221
222 /*
223 * Rgb2Yc_8BIT(r, g, b, *y, *u, *u) convert r,g,b to y,u,v
224 * Rgb2Yuv_8BIT(rgb) convert rgb to yuv
225 */
Rgb2Yc_8BIT(HI_U8 r, HI_U8 g, HI_U8 b, HI_U8 *py, HI_U8 *pcb, HI_U8 *pcr)226 __inline static HI_VOID Rgb2Yc_8BIT(HI_U8 r, HI_U8 g, HI_U8 b, HI_U8 *py, HI_U8 *pcb, HI_U8 *pcr)
227 {
228 /* Y */
229 *py = (HI_U8)(((r * 66 + g * 129 + b * 25) >> 8) + 16);
230
231 /* Cb */
232 *pcb = (HI_U8)((((b * 112 - r * 38) - g * 74) >> 8) + 128);
233
234 /* Cr */
235 *pcr = (HI_U8)((((r * 112 - g * 94) - b * 18) >> 8) + 128);
236 }
237
Rgb2Yuv_8BIT(HI_U32 u32Rgb)238 __inline static HI_U32 Rgb2Yuv_8BIT(HI_U32 u32Rgb)
239 {
240 HI_U8 y, u, v;
241
242 Rgb2Yc_8BIT(RGB_R(u32Rgb), RGB_G(u32Rgb), RGB_B(u32Rgb), &y, &u, &v);
243
244 return YUV_8BIT(y, u, v);
245 }
246
Rgb2Yc_full_8BIT(HI_U8 r, HI_U8 g, HI_U8 b, HI_U8 *py, HI_U8 *pcb, HI_U8 *pcr)247 __inline static HI_VOID Rgb2Yc_full_8BIT(HI_U8 r, HI_U8 g, HI_U8 b, HI_U8 *py, HI_U8 *pcb, HI_U8 *pcr)
248 {
249 HI_S16 py_temp, pcb_temp, pcr_temp;
250
251 py_temp = (r * 76 + g * 150 + b * 29) >> 8;
252 pcb_temp = (((b * 130 - r * 44) - g * 86) >> 8) + 128;
253 pcr_temp = (((r * 130 - g * 109) - b * 21) >> 8) + 128;
254
255 *py = MAX2(MIN2(py_temp, 255), 0);
256 *pcb = MAX2(MIN2(pcb_temp, 255), 0);
257 *pcr = MAX2(MIN2(pcr_temp, 255), 0);
258 }
259
Rgb2Yuv_full_8BIT(HI_U32 u32Rgb)260 __inline static HI_U32 Rgb2Yuv_full_8BIT(HI_U32 u32Rgb)
261 {
262 HI_U8 y, u, v;
263
264 Rgb2Yc_full_8BIT(RGB_R(u32Rgb), RGB_G(u32Rgb), RGB_B(u32Rgb), &y, &u, &v);
265
266 return YUV_8BIT(y, u, v);
267 }
268
269 /*
270 * FpsControl Using Sample:
271 * FPS_CTRL_S g_stFpsCtrl;
272 *
273 * Take 12 frame uniform in 25.
274 * InitFps(&g_stFpsCtrl, 25, 12);
275 *
276 * {
277 * if(FpsControl(&g_stFpsCtrl)) printf("Yes, this frame should be token");
278 * }
279 *
280 */
281 typedef struct hiFPS_CTRL_S {
282 HI_U32 u32Ffps; /* Full frame rate */
283 HI_U32 u32Tfps; /* Target frame rate */
284 HI_U32 u32FrmKey; /* update key frame */
285 } FPS_CTRL_S;
286
InitFps(FPS_CTRL_S *pFrmCtrl, HI_U32 u32FullFps, HI_U32 u32TagFps)287 __inline static HI_VOID InitFps(FPS_CTRL_S *pFrmCtrl, HI_U32 u32FullFps, HI_U32 u32TagFps)
288 {
289 pFrmCtrl->u32Ffps = u32FullFps;
290 pFrmCtrl->u32Tfps = u32TagFps;
291 pFrmCtrl->u32FrmKey = 0;
292 }
293
FpsControl(FPS_CTRL_S *pFrmCtrl)294 __inline static HI_BOOL FpsControl(FPS_CTRL_S *pFrmCtrl)
295 {
296 HI_BOOL bReturn = HI_FALSE;
297
298 pFrmCtrl->u32FrmKey += pFrmCtrl->u32Tfps;
299 if (pFrmCtrl->u32FrmKey >= pFrmCtrl->u32Ffps) {
300 pFrmCtrl->u32FrmKey -= pFrmCtrl->u32Ffps;
301 bReturn = HI_TRUE;
302 }
303
304 return bReturn;
305 }
306
GetLowAddr(HI_U64 u64Phyaddr)307 __inline static HI_U32 GetLowAddr(HI_U64 u64Phyaddr)
308 {
309 return (HI_U32)u64Phyaddr;
310 }
311
GetHighAddr(HI_U64 u64Phyaddr)312 __inline static HI_U32 GetHighAddr(HI_U64 u64Phyaddr)
313 {
314 return (HI_U32)(u64Phyaddr >> 32);
315 }
316
317 #define hi_usleep(usec) \
318 do { \
319 usleep(usec); \
320 } while (0)
321
322 #ifdef __cplusplus
323 #if __cplusplus
324 }
325 #endif
326 #endif /* __cplusplus */
327
328 #endif /* __HI_MATH_H__ */
329
330