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