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