/* * Copyright (c) Hisilicon Technologies Co., Ltd. 2012-2019. All rights reserved. * Description: header file of math */ #ifndef __SOC_MATH_H__ #define __SOC_MATH_H__ #include "td_type.h" #ifdef __cplusplus #if __cplusplus extern "C" { #endif #endif /* __cplusplus */ /* * soc_abs(x) absolute value of x * soc_sign(x) sign of x * soc_cmp(x,y) 0 if x==y; 1 if x>y; -1 if x= 0 ? (x) : (-(x))) #define soc_sign(x) ((x) >= 0 ? 1 : (-1)) #define soc_cmp(x, y) (((x) == (y)) ? 0 : (((x) > (y)) ? 1 : (-1))) /* * max2(x,y) maximum of x and y * min2(x,y) minimum of x and y * max3(x,y,z) maximum of x, y and z * min3(x,y,z) minimun of x, y and z * median(x,y,z) median of x,y,z * mean2(x,y) mean of x,y */ #ifndef max2 #define max2(x, y) ((x) > (y) ? (x) : (y)) #endif #ifndef min2 #define min2(x, y) ((x) < (y) ? (x) : (y)) #endif #ifndef max3 #define max3(x, y, z) ((x) > (y) ? max2(x, z) : max2(y, z)) #endif #ifndef min3 #define min3(x, y, z) ((x) < (y) ? min2(x, z) : min2(y, z)) #endif #define median(x, y, z) (((x) + (y) + (z) - max3(x, y, z)) - min3(x, y, z)) #define mean2(x, y) (((x) + (y)) >> 1) /* * clip3(x,min,max) clip x within [min,max] * wrap_max(x,max,min) wrap to min if x equal max * wrap_min(x,min,max) wrap to max if x equal min * value_between(x,min.max) True if x is between [min,max] inclusively. */ #define clip3(x, min, max) ((x) < (min) ? (min) : ((x) > (max) ? (max) : (x))) #define wrap_max(x, max, min) ((x) >= (max) ? (min) : (x)) #define wrap_min(x, min, max) ((x) <= (min) ? (max) : (x)) #define value_between(x, min, max) (((x) >= (min)) && ((x) <= (max))) /* * multi_of_2_power(x,a) whether x is multiple of a(a must be power of 2) * ceiling_2_power(x,a) ceiling x to multiple of a(a must be power of 2) * floor_2_power(x,a) floor x to multiple of a(a must be power of 2) * socalign(x, a) align x to multiple of a * * Example: * ceiling_2_power(5,4) result is 8 * floor_2_power(5,4) result is 4 */ #define multi_of_2_power(x, a) (!((x) & ((a) - 1))) #define ceiling_2_power(x, a) (((x) + ((a) - 1)) & (~((a) - 1))) #define floor_2_power(x, a) ((x) & (~((a) - 1))) #define socalign(x, a) ((a) * (((x) + (a) - 1) / (a))) #define socceiling(x, a) (((x) + (a) - 1) / (a)) #define socalign_up(x, a) ((((x) + (a) - 1) / (a)) * (a)) #define socalign_down(x, a) ((x) - (x) % (a)) #define socalign_closest(x, divisor) \ do { \ typeof(x)__x = x; \ typeof(divisor)__d = divisor; \ (((typeof(x)) - 1) > 0 || ((typeof(divisor)) - 1) > 0 || (__x) > 0) ? (((__x) + ((__d) / 2)) / (__d)) : \ (((__x) - ((__d) / 2)) / (__d)); \ } while (0) #if defined(SOC_DDRC_CHANNEL_DUAL) #define soc_sys_get_stride(w) \ ((((w) % 256) == 0) ? (w) : (((((w) / 256) % 2) == 0) ? ((((w) / 256) + 1) * 256) : ((((w) / 256) + 2) * 256))) #elif defined(SOC_DDRC_CHANNEL_SINGLE) #define soc_sys_get_stride(w) (socalign(w, 64)) #else #define soc_sys_get_stride(w) (((w) + 63) / 64 * 64) #endif /* * Get the span between two unsinged number, such as * span(td_u32, 100, 200) is 200 - 100 = 100 * span(td_u32, 200, 100) is 0xFFFFFFFF - 200 + 100 * span(td_u64, 200, 100) is 0xFFFFFFFFFFFFFFFF - 200 + 100 */ #define span(type, begin, end) \ do { \ type b = (begin); \ type e = (end); \ (type)((b >= e) ? (b - e) : (b + ((~((type)0)) - e))); \ } while (0) /* * endian32(x,y) little endian <---> big endian * is_little_end() whether the system is little end mode */ #define endian32(x) (((x) << 24) | (((x)&0x0000ff00) << 8) | (((x)&0x00ff0000) >> 8) | (((x) >> 24) & 0x000000ff)) typedef union un_end_test { td_char ctest[4]; /* 4 表示使用4个字节长度来保存用于计算大小端的数值 */ td_u32 test; } end_test_info; __inline static td_bool is_little_end(void) { end_test_info end_test; end_test.ctest[0] = 0x01; /* 0 表示第1个字节位置 */ end_test.ctest[1] = 0x02; /* 1 表示第2个字节位置 */ end_test.ctest[2] = 0x03; /* 2 表示第3个字节位置 */ end_test.ctest[3] = 0x04; /* 3 表示第4个字节位置 */ return (end_test.test > 0x01020304) ? (TD_TRUE) : (TD_FALSE); } /* * fraction32(de,nu) fraction: nu(minator) / de(nominator). * numerator32(x) of x(x is fraction) * denominator32(x) Denominator of x(x is fraction) * represent fraction in 32 bit. LSB 16 is numerator, MSB 16 is denominator * It is integer if denominator is 0. */ #define fraction32(de, nu) (((de) << 16) | (nu)) #define numerator32(x) ((x)&0xffff) #define denominator32(x) ((x) >> 16) /* ***************************************************************************** * rgb(r,g,b) assemble the r,g,b to 24bit color * rgb_r(c) get RED from 24bit color * rgb_g(c) get GREEN from 24bit color * rgb_b(c) get BLUE from 24bit color * **************************************************************************** */ #define rgb(r, g, b) ((((r) & 0xff) << 16) | (((g) & 0xff) << 8) | ((b) & 0xff)) #define rgb_r(c) (((c) & 0xff0000) >> 16) #define rgb_g(c) (((c) & 0xff00) >> 8) #define rgb_b(c) ((c) & 0xff) /* * yuv(y,u,v) assemble the y,u,v to 24bit color * yuv_y(c) get Y from 24bit color * yuv_u(c) get U from 24bit color * yuv_v(c) get V from 24bit color */ #define yuv(y, u, v) ((((y) & 0xff) << 16) | (((u) & 0xff) << 8) | ((v) & 0xff)) #define yuv_y(c) (((c) & 0xff0000) >> 16) #define yuv_u(c) (((c) & 0xff00) >> 8) #define yuv_v(c) ((c) & 0xff) /* ***************************************************************************** * rgb2yc(r, g, b, *y, *u, *u) convert r,g,b to y,u,v * rgb2yuv(rgb_data, *yuv) convert rgb to yuv * **************************************************************************** */ __inline static td_void rgb2yc(td_u8 r, td_u8 g, td_u8 b, td_u8 *py, td_u8 *pcb, td_u8 *pcr) { /* Y */ *py = (td_u8)(((r * 66 + g * 129 + b * 25) >> 8) + 16); /* 66 129 25 8 16 表示rgb转yc格式标准公式的参数 */ /* Cb */ *pcb = (td_u8)((((b * 112 - r * 38) - g * 74) >> 8) + 128); /* 112 38 74 8 128 表示rgb转yc格式标准公式的参数 */ /* Cr */ *pcr = (td_u8)((((r * 112 - g * 94) - b * 18) >> 8) + 128); /* 112 94 18 8 128 表示rgb转yc格式标准公式的参数 */ } __inline static td_u32 rgb2yuv(td_u32 rgb_data) { td_u8 y, u, v; rgb2yc(rgb_r(rgb_data), rgb_g(rgb_data), rgb_b(rgb_data), &y, &u, &v); return yuv(y, u, v); } /* ***************************************************************************** * GetYCFromRGB(rgb_data, *y, *cbcr) convert rgb to yyyy, uvuv, * **************************************************************************** */ __inline static td_void get_yc_from_rgb(td_u32 rgb_data, td_u32 *py, td_u32 *pc) { td_u8 y, cb, cr; td_u32 color_y, color_c; rgb2yc(rgb_r(rgb_data), rgb_g(rgb_data), rgb_b(rgb_data), &y, &cb, &cr); /* 24 16 18 8 表示计算color_y偏移位数 */ color_y = ((y & 0xFF) << 24) + ((y & 0xFF) << 16) + ((y & 0xFF) << 8) + (y & 0xFF); color_c = ((cb & 0xFF) << 24) + ((cb & 0xFF) << 8); /* 24 8 表示计算color_c偏移位数 */ color_c = color_c + ((cr & 0xFF) << 16) + (cr & 0xFF); /* 16 表示计算color_c偏移位数 */ *py = color_y; *pc = color_c; } /* ****************************************************************************** * fps_control Useing Sample: * fps_ctrl g_stFpsCtrl; * * Take 12 frame uniform in 25. * call like this : init_fps(&g_stFpsCtrl, 25, 12) * if fps_control(&g_stFpsCtrl) return true * then printf "Yes, this frmae should be token" * * ***************************************************************************** */ typedef struct soc_fps_ctrl { td_u32 ffps; /* Full frame rate */ td_u32 tfps; /* Target frame rate */ td_u32 frm_key; /* update key frame */ } fps_ctrl; __inline static td_void init_fps(fps_ctrl *frm_cttl_ptr, td_u32 full_fps, td_u32 tag_fps) { frm_cttl_ptr->ffps = full_fps; frm_cttl_ptr->tfps = tag_fps; frm_cttl_ptr->frm_key = 0; } __inline static td_bool fps_control(fps_ctrl *frm_cttl_ptr) { td_bool ret = TD_FALSE; frm_cttl_ptr->frm_key += frm_cttl_ptr->tfps; if (frm_cttl_ptr->frm_key >= frm_cttl_ptr->ffps) { frm_cttl_ptr->frm_key -= frm_cttl_ptr->ffps; ret = TD_TRUE; } return ret; } #ifdef __cplusplus #if __cplusplus } #endif #endif /* __cplusplus */ #endif /* __SOC_MATH_H__ */