#include #include #include #include #include #include #include #include #include #include "cutils/log.h" #include "iep_api.h" #include "rga.h" #define PI (3.1415926) #define X (-1) static int enh_alpha_table[][25] = { // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 /*0*/ {X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X }, /*1*/ {0, 8, 12, 16, 20, 24, 28, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X }, /*2*/ {0, 4, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, X, X, X, X, X, X, X, X, X, X, X, X }, /*3*/ {0, X, X, 8, X, X, 12, X, X, 16, X, X, 20, X, X, 24, X, X, 28, X, X, X, X, X, X }, /*4*/ {0, 2, 4, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28 }, /*5*/ {0, X, X, X, X, 8, X, X, X, X, 12, X, X, X, X, 16, X, X, X, X, 20, X, X, X, X }, /*6*/ {0, X, X, 4, X, X, 8, X, X, 10, X, X, 12, X, X, 14, X, X, 16, X, X, 18, X, X, 20 }, /*7*/ {0, X, X, X, X, X, X, 8, X, X, X, X, X, X, 12, X, X, X, X, X, X, 16, X, X, X }, /*8*/ {0, 1, 2, 3, 4, 5, 6, 7, 8, X, 9, X, 10, X, 11, X, 12, X, 13, X, 14, X, 15, X, 16 } }; // rr = 1.7 rg = 1 rb = 0.6 static unsigned int cg_tab[] = { 0x01010100, 0x03020202, 0x04030303, 0x05040404, 0x05050505, 0x06060606, 0x07070606, 0x07070707, 0x08080807, 0x09080808, 0x09090909, 0x0a090909, 0x0a0a0a0a, 0x0b0a0a0a, 0x0b0b0b0b, 0x0c0b0b0b, 0x0c0c0c0c, 0x0c0c0c0c, 0x0d0d0d0d, 0x0d0d0d0d, 0x0e0e0d0d, 0x0e0e0e0e, 0x0e0e0e0e, 0x0f0f0f0f, 0x0f0f0f0f, 0x10100f0f, 0x10101010, 0x10101010, 0x11111110, 0x11111111, 0x11111111, 0x12121212, 0x12121212, 0x12121212, 0x13131313, 0x13131313, 0x13131313, 0x14141414, 0x14141414, 0x14141414, 0x15151515, 0x15151515, 0x15151515, 0x16161615, 0x16161616, 0x16161616, 0x17161616, 0x17171717, 0x17171717, 0x17171717, 0x18181818, 0x18181818, 0x18181818, 0x19191818, 0x19191919, 0x19191919, 0x19191919, 0x1a1a1a19, 0x1a1a1a1a, 0x1a1a1a1a, 0x1a1a1a1a, 0x1b1b1b1b, 0x1b1b1b1b, 0x1b1b1b1b, 0x03020100, 0x07060504, 0x0b0a0908, 0x0f0e0d0c, 0x13121110, 0x17161514, 0x1b1a1918, 0x1f1e1d1c, 0x23222120, 0x27262524, 0x2b2a2928, 0x2f2e2d2c, 0x33323130, 0x37363534, 0x3b3a3938, 0x3f3e3d3c, 0x43424140, 0x47464544, 0x4b4a4948, 0x4f4e4d4c, 0x53525150, 0x57565554, 0x5b5a5958, 0x5f5e5d5c, 0x63626160, 0x67666564, 0x6b6a6968, 0x6f6e6d6c, 0x73727170, 0x77767574, 0x7b7a7978, 0x7f7e7d7c, 0x83828180, 0x87868584, 0x8b8a8988, 0x8f8e8d8c, 0x93929190, 0x97969594, 0x9b9a9998, 0x9f9e9d9c, 0xa3a2a1a0, 0xa7a6a5a4, 0xabaaa9a8, 0xafaeadac, 0xb3b2b1b0, 0xb7b6b5b4, 0xbbbab9b8, 0xbfbebdbc, 0xc3c2c1c0, 0xc7c6c5c4, 0xcbcac9c8, 0xcfcecdcc, 0xd3d2d1d0, 0xd7d6d5d4, 0xdbdad9d8, 0xdfdedddc, 0xe3e2e1e0, 0xe7e6e5e4, 0xebeae9e8, 0xefeeedec, 0xf3f2f1f0, 0xf7f6f5f4, 0xfbfaf9f8, 0xfffefdfc, 0x06030100, 0x1b150f0a, 0x3a322922, 0x63584e44, 0x95887b6f, 0xcebfb0a2, 0xfffeedde, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }; #define IEP_DEB(fmt, args...) do { \ if (g_log_level > 0) { \ ALOGD(__FILE__ ",%s,:%d: " fmt, __func__, __LINE__, ## args); \ } \ } while (0) #define IEP_ERR(fmt, args...) ALOGE(__FILE__ ",%s,:%d: " fmt, __func__, __LINE__, ## args) class iep_api : public iep_interface { private: IEP_MSG *msg; int fd; pthread_t td_notify; iep_notify notify; int pid; int rga_fd; int iommu; public: iep_api(); ~iep_api(); virtual int init(iep_img *src, iep_img *dst); virtual int config_src_dst(iep_img *src, iep_img *dst); virtual int config_yuv_enh(); virtual int config_yuv_enh(iep_param_YUV_color_enhance_t *yuv_enh); virtual int config_color_enh(); virtual int config_color_enh(iep_param_RGB_color_enhance_t *rgb_enh); virtual int config_scale(); virtual int config_scale(iep_param_scale *scale); virtual int config_yuv_denoise(); virtual int config_yuv_denoise(iep_img *src_itemp, iep_img *src_ftemp, iep_img *dst_itemp, iep_img *dst_ftemp); virtual int config_yuv_deinterlace(); virtual int config_yuv_deinterlace(iep_param_yuv_deinterlace_t *yuv_dil); virtual int config_yuv_dil_src_dst(iep_img *src1, iep_img *dst1); virtual int config_yuv_deinterlace(iep_param_yuv_deinterlace_t *yuv_dil, iep_img *src1, iep_img *dst1); virtual int config_color_space_convertion(); virtual int config_color_space_convertion( iep_param_color_space_convertion_t *clr_convert); virtual int config_direct_lcdc_path( iep_param_direct_path_interface_t *dpi); virtual int run_sync(); virtual int run_async(iep_notify notify); virtual int poll(); virtual struct IEP_CAP* query(); virtual IEP_QUERY_INTERLACE query_interlace(); virtual IEP_QUERY_DIMENSION query_dimension(); private: static void* notify_func(void *param); int yuv_enh_sanity_check(iep_param_YUV_color_enhance_t *yuv_enh); int rgb_enh_sanity_check(iep_param_RGB_color_enhance_t *rgb_enh); int direct_lcdc_path_sanity_check(iep_param_direct_path_interface_t *dpi); int yuv_denoise_sanity_check(iep_img *src_itemp, iep_img *src_ftemp, iep_img *dst_itemp, iep_img *dst_ftemp); int dil_src_dst_sanity_check(iep_img *src1, iep_img *dst1); int deinterlace_sanity_check(iep_param_yuv_deinterlace_t *yuv_dil, iep_img *src1, iep_img *dst1); int color_space_convertion_sanity_check(iep_param_color_space_convertion_t *clr_convert); int init_sanity_check(iep_img *src, iep_img *dst); void recover_image(struct rga_req *req, iep_img *dst); void recover_image1(struct rga_req *req); }; static int g_mode = 0; static int g_log_level = 0; static pthread_once_t g_get_env_value_once = PTHREAD_ONCE_INIT; static struct IEP_CAP cap; static void get_env_value() { char prop_value[PROPERTY_VALUE_MAX]; if (property_get("iep.mode.control", prop_value, NULL)) g_mode = atoi(prop_value); if (property_get("iep.log_level.control", prop_value, NULL)) g_log_level = atoi(prop_value); } iep_api::iep_api() : rga_fd(-1) { //pthread_once(&g_get_env_value_once, get_env_value); get_env_value(); ALOGD("g_mode %d, g_log_level %d\n", g_mode, g_log_level); msg = new IEP_MSG(); if (msg == NULL) { IEP_ERR("memory allocated failed\n"); abort(); } memset(msg, 0, sizeof(IEP_MSG)); fd = open("/dev/iep", O_RDWR); if (fd < 0) { IEP_ERR("file open failed\n"); abort(); } pid = getpid(); IEP_DEB("query capabilities\n"); if (0 > ioctl(fd, IEP_QUERY_CAP, &cap)) { IEP_DEB("Query IEP capability failed, using default cap\n"); cap.scaling_supported = 0; cap.i4_deinterlace_supported = 1; cap.i2_deinterlace_supported = 1; cap.compression_noise_reduction_supported = 1; cap.sampling_noise_reduction_supported = 1; cap.hsb_enhancement_supported = 1; cap.cg_enhancement_supported = 1; cap.direct_path_supported = 1; cap.max_dynamic_width = 1920; cap.max_dynamic_height = 1088; cap.max_static_width = 8192; cap.max_static_height = 8192; cap.max_enhance_radius = 3; } iommu = 0; if (0 > ioctl(fd, IEP_GET_IOMMU_STATE, &iommu)) { IEP_DEB("Get iommu state failed, mismatch library and driver, disable contrast mode\n"); g_mode = 0; } if (g_mode) { rga_fd = open("/dev/rga", O_RDWR); if (rga_fd < 0) { IEP_ERR("rga device open failed\n"); abort(); } } } iep_api::~iep_api() { if (msg->lcdc_path_en) { iep_param_direct_path_interface_t dpi; dpi.enable = 0; config_direct_lcdc_path(&dpi); run_sync(); } if (fd > 0) { close(fd); } if (rga_fd > 0) { close(rga_fd); } if (msg) { delete msg; } } int iep_api::config_yuv_enh() { msg->yuv_enhance_en = 1; msg->sat_con_int = 0x80; msg->contrast_int = 0x80; // hue_angle = 0 msg->cos_hue_int = 0x00; msg->sin_hue_int = 0x80; msg->yuv_enh_brightness = 0x00; msg->video_mode = IEP_VIDEO_MODE_NORMAL_VIDEO; msg->color_bar_u = 0; msg->color_bar_v = 0; msg->color_bar_y = 0; return 0; } int iep_api::config_yuv_enh(iep_param_YUV_color_enhance_t *yuv_enh) { do { if (0 > yuv_enh_sanity_check(yuv_enh)) { break; } msg->yuv_enhance_en = 1; msg->sat_con_int = (int)(yuv_enh->yuv_enh_saturation * yuv_enh->yuv_enh_contrast * 128); msg->contrast_int = (int)(yuv_enh->yuv_enh_contrast * 128); msg->cos_hue_int = (int)(cos(yuv_enh->yuv_enh_hue_angle) * 128.0); msg->sin_hue_int = (int)(sin(yuv_enh->yuv_enh_hue_angle) * 128.0); msg->yuv_enh_brightness = yuv_enh->yuv_enh_brightness >= 0 ? yuv_enh->yuv_enh_brightness : (yuv_enh->yuv_enh_brightness + 64); msg->video_mode = yuv_enh->video_mode; msg->color_bar_y = yuv_enh->color_bar_y; msg->color_bar_u = yuv_enh->color_bar_u; msg->color_bar_v = yuv_enh->color_bar_v; return 0; } while (0); return -1; } int iep_api::config_color_enh() { //int i; msg->rgb_color_enhance_en = 1; msg->rgb_enh_coe = 32; msg->rgb_contrast_enhance_mode = IEP_RGB_COLOR_ENHANCE_MODE_DETAIL_ENHANCE; msg->rgb_cg_en = 0; msg->enh_threshold = 255; msg->enh_alpha = 8; msg->enh_radius = 3; /*for (i=0; icg_tab[i] = cg_tab[i]; }*/ return 0; } int iep_api::config_color_enh(iep_param_RGB_color_enhance_t *rgb_enh) { do { int i; unsigned int rgb_0, rgb_1, rgb_2, rgb_3; unsigned int cg_0, cg_1, cg_2, cg_3; unsigned int tab_0, tab_1, tab_2, tab_3; unsigned int conf_value; if (0 > rgb_enh_sanity_check(rgb_enh)) { break; } msg->rgb_color_enhance_en = 1; msg->rgb_enh_coe = (unsigned int)(rgb_enh->rgb_enh_coe * 32); msg->rgb_contrast_enhance_mode = rgb_enh->rgb_contrast_enhance_mode; msg->rgb_cg_en = rgb_enh->rgb_cg_en; msg->rgb_enhance_mode = rgb_enh->rgb_enhance_mode; msg->enh_threshold = rgb_enh->enh_threshold; msg->enh_alpha = enh_alpha_table[rgb_enh->enh_alpha_base][rgb_enh->enh_alpha_num]; msg->enh_radius = rgb_enh->enh_radius - 1; if (rgb_enh->rgb_cg_en) { //for b for (i = 0; i < 64; i++) { rgb_0 = 4 * i; rgb_1 = 4 * i + 1; rgb_2 = 4 * i + 2; rgb_3 = 4 * i + 3; /// need modify later cg_0 = pow(rgb_0, rgb_enh->cg_rb); cg_1 = pow(rgb_1, rgb_enh->cg_rb); cg_2 = pow(rgb_2, rgb_enh->cg_rb); cg_3 = pow(rgb_3, rgb_enh->cg_rb); if (cg_0 > 255) cg_0 = 255; if (cg_1 > 255) cg_1 = 255; if (cg_2 > 255) cg_2 = 255; if (cg_3 > 255) cg_3 = 255; tab_0 = (unsigned int)cg_0; tab_1 = (unsigned int)cg_1; tab_2 = (unsigned int)cg_2; tab_3 = (unsigned int)cg_3; conf_value = (tab_3 << 24) + (tab_2 << 16) + (tab_1 << 8) + tab_0; msg->cg_tab[i] = conf_value; } //for g for (i = 0; i < 64; i++) { rgb_0 = 4 * i; rgb_1 = 4 * i + 1; rgb_2 = 4 * i + 2; rgb_3 = 4 * i + 3; /// need to modify later cg_0 = pow(rgb_0, rgb_enh->cg_rg); cg_1 = pow(rgb_1, rgb_enh->cg_rg); cg_2 = pow(rgb_2, rgb_enh->cg_rg); cg_3 = pow(rgb_3, rgb_enh->cg_rg); if (cg_0 > 255) cg_0 = 255; if (cg_1 > 255) cg_1 = 255; if (cg_2 > 255) cg_2 = 255; if (cg_3 > 255) cg_3 = 255; tab_0 = (unsigned int)cg_0; tab_1 = (unsigned int)cg_1; tab_2 = (unsigned int)cg_2; tab_3 = (unsigned int)cg_3; conf_value = (tab_3 << 24) + (tab_2 << 16) + (tab_1 << 8) + tab_0; msg->cg_tab[64+i] = conf_value; } //for r for (i = 0; i <= 63; i = i + 1) { rgb_0 = 4 * i; rgb_1 = 4 * i + 1; rgb_2 = 4 * i + 2; rgb_3 = 4 * i + 3; // need to modify later cg_0 = pow(rgb_0, rgb_enh->cg_rr); cg_1 = pow(rgb_1, rgb_enh->cg_rr); cg_2 = pow(rgb_2, rgb_enh->cg_rr); cg_3 = pow(rgb_3, rgb_enh->cg_rr); if (cg_0 > 255) cg_0 = 255; if (cg_1 > 255) cg_1 = 255; if (cg_2 > 255) cg_2 = 255; if (cg_3 > 255) cg_3 = 255; tab_0 = (unsigned int)cg_0; tab_1 = (unsigned int)cg_1; tab_2 = (unsigned int)cg_2; tab_3 = (unsigned int)cg_3; conf_value = (tab_3 << 24) + (tab_2 << 16) + (tab_1 << 8) + tab_0; msg->cg_tab[2*64+i] = conf_value; } } return 0; } while (0); return -1; } int iep_api::config_scale() { msg->scale_up_mode = IEP_SCALE_UP_MODE_CATROM; return 0; } int iep_api::config_scale(iep_param_scale *scale) { do { if (scale == NULL) { IEP_ERR("Invalidate parameter!\n"); break; } msg->scale_up_mode = scale->scale_up_mode; return 0; } while (0); return -1; } int iep_api::config_yuv_denoise() { /*do { msg->yuv_3D_denoise_en = 1; return 0; } while (0);*/ IEP_ERR("NOT available in this version\n"); return -1; } int iep_api::config_yuv_denoise(iep_img *src_itemp, iep_img *src_ftemp, iep_img *dst_itemp, iep_img *dst_ftemp) { do { if (0 > yuv_denoise_sanity_check(src_itemp, src_ftemp, dst_itemp, dst_ftemp)) { break; } memcpy(&msg->src_itemp, src_itemp, sizeof(iep_img)); memcpy(&msg->src_ftemp, src_ftemp, sizeof(iep_img)); memcpy(&msg->dst_itemp, dst_itemp, sizeof(iep_img)); memcpy(&msg->dst_ftemp, dst_ftemp, sizeof(iep_img)); if (g_mode) { msg->src_itemp.act_w /= 2; msg->src_ftemp.act_w /= 2; msg->dst_itemp.act_w /= 2; msg->dst_ftemp.act_w /= 2; msg->src_itemp.x_off = msg->src_itemp.act_w; msg->src_ftemp.x_off = msg->src_ftemp.act_w; msg->dst_itemp.x_off = msg->dst_itemp.act_w; msg->dst_ftemp.x_off = msg->dst_ftemp.act_w; } msg->yuv_3D_denoise_en = 1; return 0; } while (0); return -1; } int iep_api::config_yuv_deinterlace() { msg->dein_high_fre_en = 0; msg->dein_mode = IEP_DEINTERLACE_MODE_I2O1; msg->field_order = FIELD_ORDER_BOTTOM_FIRST; msg->dein_ei_mode = 0; msg->dein_ei_sel = 0; msg->dein_ei_radius = 0; msg->dein_ei_smooth = 0; msg->dein_high_fre_fct = 0; return 0; } int iep_api::config_yuv_deinterlace(iep_param_yuv_deinterlace_t *yuv_dil) { do { if (yuv_dil == NULL) { break; } msg->dein_high_fre_en = yuv_dil->high_freq_en; msg->dein_mode = yuv_dil->dil_mode; msg->field_order = yuv_dil->field_order; msg->dein_ei_mode = yuv_dil->dil_ei_mode; msg->dein_ei_sel = yuv_dil->dil_ei_sel; msg->dein_ei_radius = yuv_dil->dil_ei_radius; msg->dein_ei_smooth = yuv_dil->dil_ei_smooth; msg->dein_high_fre_fct = yuv_dil->dil_high_freq_fct; return 0; } while (0); return -1; } int iep_api::config_yuv_dil_src_dst(iep_img *src1, iep_img *dst1) { do { if (0 > dil_src_dst_sanity_check(src1, dst1)) { break; } if (src1 != NULL) { memcpy(&msg->src1, src1, sizeof(iep_img)); } if (dst1 != NULL) { memcpy(&msg->dst1, dst1, sizeof(iep_img)); } if (g_mode) { msg->src1.act_w /= 2; msg->dst1.act_w /= 2; msg->src1.x_off = msg->src1.act_w; msg->dst1.x_off = msg->dst1.act_w; } return 0; } while (0); return -1; } int iep_api::config_yuv_deinterlace(iep_param_yuv_deinterlace_t *yuv_dil, iep_img *src1, iep_img *dst1) { do { if (0 > deinterlace_sanity_check(yuv_dil, src1, dst1)) { break; } msg->dein_high_fre_en = yuv_dil->high_freq_en; msg->dein_mode = yuv_dil->dil_mode; msg->field_order = yuv_dil->field_order; msg->dein_ei_mode = yuv_dil->dil_ei_mode; msg->dein_ei_sel = yuv_dil->dil_ei_sel; msg->dein_ei_radius = yuv_dil->dil_ei_radius; msg->dein_ei_smooth = yuv_dil->dil_ei_smooth; msg->dein_high_fre_fct = yuv_dil->dil_high_freq_fct; if (src1 != NULL) { memcpy(&msg->src1, src1, sizeof(iep_img)); } if (dst1 != NULL) { memcpy(&msg->dst1, dst1, sizeof(iep_img)); } if (g_mode) { msg->src1.act_w /= 2; msg->dst1.act_w /= 2; msg->src1.x_off = msg->src1.act_w; msg->dst1.x_off = msg->dst1.act_w; } return 0; } while (0); return -1; } int iep_api::config_color_space_convertion() { msg->rgb2yuv_mode = IEP_COLOR_CONVERT_MODE_BT601_L; msg->yuv2rgb_mode = IEP_COLOR_CONVERT_MODE_BT601_L; msg->rgb2yuv_clip_en = 0; msg->yuv2rgb_clip_en = 0; msg->global_alpha_value = 0; msg->dither_up_en = 1; msg->dither_down_en = 1; return 0; } int iep_api::config_color_space_convertion( iep_param_color_space_convertion_t *clr_convert) { do { if (0 > color_space_convertion_sanity_check(clr_convert)) { break; } msg->rgb2yuv_mode = clr_convert->rgb2yuv_mode; msg->yuv2rgb_mode = clr_convert->yuv2rgb_mode; msg->rgb2yuv_clip_en = clr_convert->rgb2yuv_input_clip; msg->yuv2rgb_clip_en = clr_convert->yuv2rgb_input_clip; msg->global_alpha_value = clr_convert->global_alpha_value; msg->dither_up_en = clr_convert->dither_up_en; msg->dither_down_en = clr_convert->dither_down_en; return 0; } while (0); return -1; } int iep_api::config_direct_lcdc_path(iep_param_direct_path_interface_t *dpi) { do { if (0 > direct_lcdc_path_sanity_check(dpi)) { break; } msg->lcdc_path_en = dpi->enable; msg->off_x = dpi->off_x; msg->off_y = dpi->off_y; msg->width = dpi->width; msg->height = dpi->height; msg->layer = dpi->layer; return 0; } while (0); return -1; } int iep_api::config_src_dst(iep_img *src, iep_img *dst) { do { if (0 > init_sanity_check(src, dst)) { break; } memcpy(&msg->src, src, sizeof(iep_img)); memcpy(&msg->dst, dst, sizeof(iep_img)); if (g_mode) { msg->src.act_w /= 2; msg->src.x_off = msg->src.act_w; msg->dst.act_w /= 2; msg->dst.x_off = msg->dst.act_w; } if ((src->format == IEP_FORMAT_YCbCr_420_P || src->format == IEP_FORMAT_YCbCr_420_SP || src->format == IEP_FORMAT_YCbCr_422_P || src->format == IEP_FORMAT_YCbCr_422_SP || src->format == IEP_FORMAT_YCrCb_420_P || src->format == IEP_FORMAT_YCrCb_420_SP || src->format == IEP_FORMAT_YCrCb_422_P || src->format == IEP_FORMAT_YCrCb_422_SP) && msg->dein_mode == IEP_DEINTERLACE_MODE_DISABLE) { msg->dein_mode = IEP_DEINTERLACE_MODE_BYPASS; } return 0; } while (0); return -1; } int iep_api::init(iep_img *src, iep_img *dst) { do { if (0 > init_sanity_check(src, dst)) { break; } memset(msg, 0, sizeof(IEP_MSG)); memcpy(&msg->src, src, sizeof(iep_img)); memcpy(&msg->dst, dst, sizeof(iep_img)); if (g_mode) { msg->src.act_w /= 2; msg->src.x_off = msg->src.act_w; msg->dst.act_w /= 2; msg->dst.x_off = msg->dst.act_w; } if ((src->format == IEP_FORMAT_YCbCr_420_P || src->format == IEP_FORMAT_YCbCr_420_SP || src->format == IEP_FORMAT_YCbCr_422_P || src->format == IEP_FORMAT_YCbCr_422_SP || src->format == IEP_FORMAT_YCrCb_420_P || src->format == IEP_FORMAT_YCrCb_420_SP || src->format == IEP_FORMAT_YCrCb_422_P || src->format == IEP_FORMAT_YCrCb_422_SP) && msg->dein_mode == IEP_DEINTERLACE_MODE_DISABLE) { msg->dein_mode = IEP_DEINTERLACE_MODE_BYPASS; } return 0; } while (0); return -1; } void iep_api::recover_image(struct rga_req *req, iep_img *dst) { if (iommu) { req->src.yrgb_addr = msg->src.mem_addr; req->src.uv_addr = 0;//msg->src.uv_addr; req->src.v_addr = 0;//msg->src.v_addr; } else { req->src.yrgb_addr = 0; req->src.uv_addr = msg->src.mem_addr; req->src.v_addr = 0; } req->src.vir_w = msg->src.vir_w; req->src.vir_h = msg->src.vir_h; req->src.format = RK_FORMAT_YCbCr_420_SP; req->src.alpha_swap |= 0; req->src.act_w = msg->src.act_w; req->src.act_h = msg->src.act_h; req->src.x_offset = 0; req->src.y_offset = 0; if (iommu) { req->dst.yrgb_addr = dst->mem_addr; req->dst.uv_addr = 0;//msg->dst.uv_addr; req->dst.v_addr = 0;//msg->dst.v_addr; } else { req->dst.yrgb_addr = 0; req->dst.uv_addr = dst->mem_addr; req->dst.v_addr = 0; } req->dst.vir_w = dst->vir_w; req->dst.vir_h = dst->vir_h; req->dst.format = RK_FORMAT_YCbCr_420_SP; req->clip.xmin = 0; req->clip.xmax = dst->vir_w - 1; req->clip.ymin = 0; req->clip.ymax = dst->vir_h - 1; req->dst.alpha_swap |= 0; req->dst.act_w = dst->act_w; req->dst.act_h = dst->act_h; req->dst.x_offset = 0; req->dst.y_offset = 0; IEP_DEB("src y %x u %x v %x, dst y %x u %x v %x\n", req->src.yrgb_addr, req->src.uv_addr, req->src.v_addr, req->dst.yrgb_addr, req->dst.uv_addr, req->dst.v_addr); IEP_DEB("src vir %d x %d, dst vir %d x %d\n", req->src.vir_w, req->src.vir_h, req->dst.vir_w, req->dst.vir_h); IEP_DEB("src act %d x %d, offset (%d, %d), dst act %d x %d, offset (%d, %d)\n", req->src.act_w, req->src.act_h, req->src.x_offset, req->src.y_offset, req->dst.act_w, req->dst.act_h, req->dst.x_offset, req->dst.y_offset); } int iep_api::run_sync() { do { struct rga_req req; if (0 > ioctl(fd, IEP_SET_PARAMETER, (void *)msg)) { IEP_ERR("ioctl IEP_SET_PARAMETER failure\n"); break; } if (g_mode) { memset(&req, 0, sizeof(struct rga_req)); recover_image(&req, &msg->dst); if (iommu) { req.mmu_info.mmu_en = 1; req.mmu_info.mmu_flag = 1 | (1 << 8) | (1 << 10) | (1 << 31); } else { req.mmu_info.mmu_en = 0; } if (0 > ioctl(rga_fd, RGA_BLIT_SYNC, &req)) { IEP_ERR("RGA_BLIT_SYNC failed\n"); } if (msg->dein_mode == IEP_DEINTERLACE_MODE_I4O2) { memset(&req, 0, sizeof(struct rga_req)); recover_image(&req, &msg->dst1); if (iommu) { req.mmu_info.mmu_en = 1; req.mmu_info.mmu_flag = 1 | (1 << 8) | (1 << 10) | (1 << 31); } else { req.mmu_info.mmu_en = 0; } if (0 > ioctl(rga_fd, RGA_BLIT_SYNC, &req)) { IEP_ERR("RGA_BLIT_SYNC failed\n"); } } } if (0 > ioctl(fd, IEP_GET_RESULT_SYNC, 0)) { IEP_ERR("%d, failure\n", pid); break; } return 0; } while (0); return -1; } void* iep_api::notify_func(void *param) { iep_api *api = (iep_api *)param; int result = 0; fd_set rfds; struct timespec tv; int status; sigset_t set; FD_ZERO(&rfds); FD_SET(api->fd, &rfds); tv.tv_sec = 0; tv.tv_nsec = 2e9; sigemptyset(&set); sigaddset(&set, SIGALRM); status = pselect(api->fd + 1, &rfds, NULL, NULL, &tv, &set); if (0 == status) { IEP_ERR("%d, timeout\n", api->pid); ioctl(api->fd, IEP_GET_RESULT_SYNC, NULL); result = -1; } else if (-1 == status) { IEP_ERR("%d, error\n", api->pid); ioctl(api->fd, IEP_RELEASE_CURRENT_TASK, NULL); result = -2; } else if (FD_ISSET(api->fd, &rfds)) { IEP_DEB("%d, success\n", api->pid); result = 0; } api->notify(result); return NULL; } int iep_api::run_async(iep_notify notify) { do { if (notify != NULL) { this->notify = notify; if (0 != pthread_create(&td_notify, NULL, iep_api::notify_func, this)) { IEP_ERR("internal error\n"); break; } } if (0 > ioctl(fd, IEP_SET_PARAMETER, msg)) { IEP_ERR("ioctl IEP_SET_PARAMETER failure\n"); break; } if (0 > ioctl(fd, IEP_GET_RESULT_ASYNC, 0)) { IEP_ERR("%d, failure\n", pid); break; } return 0; } while (0); return -1; } int iep_api::poll() { int result = 0; fd_set rfds; struct timespec tv; int status; sigset_t set; FD_ZERO(&rfds); FD_SET(this->fd, &rfds); tv.tv_sec = 0; tv.tv_nsec = 2e9; sigemptyset(&set); sigaddset(&set, SIGALRM); status = pselect(this->fd + 1, &rfds, NULL, NULL, &tv, &set); if (0 == status) { IEP_ERR("%d, timeout\n", this->pid); ioctl(this->fd, IEP_GET_RESULT_SYNC, NULL); result = -1; } else if (-1 == status) { IEP_ERR("%d, error\n", this->pid); ioctl(this->fd, IEP_RELEASE_CURRENT_TASK, NULL); result = -2; } else if (FD_ISSET(this->fd, &rfds)) { IEP_DEB("%d, success\n", this->pid); result = 0; } return result; } int iep_api::yuv_enh_sanity_check(iep_param_YUV_color_enhance_t *yuv_enh) { do { if (yuv_enh == NULL) { IEP_ERR("Invalidate parameter!\n"); break; } if (yuv_enh->yuv_enh_saturation < 0 || yuv_enh->yuv_enh_saturation > 1.992) { IEP_ERR("Invalidate parameter, yuv_enh_saturation!\n"); break; } if (yuv_enh->yuv_enh_contrast < 0 || yuv_enh->yuv_enh_contrast > 1.992) { IEP_ERR("Invalidate parameter, yuv_enh_contrast!\n"); break; } if (yuv_enh->yuv_enh_brightness < -32 || yuv_enh->yuv_enh_brightness > 31) { IEP_ERR("Invalidate parameter, yuv_enh_brightness!\n"); break; } if (yuv_enh->yuv_enh_hue_angle < -30 || yuv_enh->yuv_enh_hue_angle > 30) { IEP_ERR("Invalidate parameter, yuv_enh_hue_angle!\n"); break; } if (yuv_enh->video_mode < 0 || yuv_enh->video_mode > 3) { IEP_ERR("Invalidate parameter, video_mode!\n"); break; } if (yuv_enh->color_bar_y > 127 || yuv_enh->color_bar_u > 127 || yuv_enh->color_bar_v > 127) { IEP_ERR("Invalidate parameter, color_bar_*!\n"); break; } if (msg->src.format >= 1 && msg->src.format <= 5 && msg->dst.format >= 1 && msg->dst.format <= 5) { IEP_ERR("Invalidate parameter, contradition between in/out format and yuv enhance\n"); break; } return 0; } while (0); return -1; } int iep_api::rgb_enh_sanity_check(iep_param_RGB_color_enhance_t *rgb_enh) { do { if (rgb_enh == NULL) { IEP_ERR("Invalidate parameter!\n"); break; } if (rgb_enh->enh_alpha_base > 8 || rgb_enh->enh_alpha_base < 0 || rgb_enh->enh_alpha_num < 0 || rgb_enh->enh_alpha_num > 24) { IEP_ERR("Invalidate parameter, enh_alpha_base or enh_alpha_num!\n"); break; } if (enh_alpha_table[rgb_enh->enh_alpha_base][rgb_enh->enh_alpha_num] == -1) { IEP_ERR("Invalidate parameter, enh_alpha_base or enh_alpha_num!\n"); break; } if (rgb_enh->enh_threshold > 255 || rgb_enh->enh_threshold < 0) { IEP_ERR("Invalidate parameter, enh_threshold!\n"); break; } if (rgb_enh->enh_radius > 4 || rgb_enh->enh_radius < 1) { IEP_ERR("Invalidate parameter, enh_radius!\n"); break; } if (rgb_enh->rgb_contrast_enhance_mode < 0 || rgb_enh->rgb_contrast_enhance_mode > 1) { IEP_ERR("Invalidate parameter, rgb_contrast_enhance_mode!\n"); break; } if (rgb_enh->rgb_enhance_mode < 0 || rgb_enh->rgb_enhance_mode > 3) { IEP_ERR("Invalidate parameter, rgb_enhance_mode!\n"); break; } if (rgb_enh->rgb_enh_coe > 3.96875 || rgb_enh->rgb_enh_coe < 0) { IEP_ERR("Invalidate parameter, rgb_enh_coe!\n"); break; } if (msg->src.format >= 10 && msg->src.format <= 17 && msg->dst.format >= 10 && msg->dst.format <= 17) { IEP_ERR("Invalidate parameter, contradition between in/out format and yuv enhance\n"); break; } return 0; } while (0); return -1; } int iep_api::color_space_convertion_sanity_check(iep_param_color_space_convertion_t *clr_convert) { do { if (clr_convert == NULL) { IEP_ERR("Invalidate parameter!\n"); break; } if (clr_convert->dither_up_en && msg->src.format != IEP_FORMAT_RGB_565) { IEP_ERR("Invalidate parameter, contradiction between dither up enable and source image format!\n"); break; } if (clr_convert->dither_down_en && msg->dst.format != IEP_FORMAT_RGB_565) { IEP_ERR("Invalidate parameter, contradiction between dither down enable and destination image format!\n"); break; } return 0; } while (0); return -1; } int iep_api::yuv_denoise_sanity_check(iep_img *src_itemp, iep_img *src_ftemp, iep_img *dst_itemp, iep_img *dst_ftemp) { do { if (src_itemp == NULL || src_ftemp == NULL || dst_itemp == NULL || dst_ftemp == NULL) { IEP_ERR("Invalidate parameter!\n"); break; } return 0; } while (0); return -1; } int iep_api::dil_src_dst_sanity_check(iep_img *src1, iep_img *dst1) { do { switch (msg->dein_mode) { case IEP_DEINTERLACE_MODE_I4O2: if (dst1 == NULL) { IEP_ERR("Invalidate parameter!\n"); goto err; } else if (!g_mode && (dst1->act_w != msg->dst.act_w || dst1->act_h != msg->dst.act_h)) { IEP_ERR("Invalidate parameter, contradiction between two destination image size!\n"); goto err; } case IEP_DEINTERLACE_MODE_I4O1: if (src1 == NULL) { IEP_ERR("Invalidate parameter!\n"); goto err; } else if (!g_mode && (src1->act_w != msg->src.act_w || src1->act_h != msg->src.act_h)) { IEP_ERR("Invalidate parameter, contradiction between two source image size!\n"); goto err; } case IEP_DEINTERLACE_MODE_I2O1: if (msg->src.act_w > 1920) { goto err; } break; default: ; } return 0; } while (0); err: return -1; } int iep_api::deinterlace_sanity_check(iep_param_yuv_deinterlace_t *yuv_dil, iep_img *src1, iep_img *dst1) { do { if (yuv_dil == NULL) { IEP_ERR("Invalidate parameter!\n"); break; } if (yuv_dil->dil_mode == IEP_DEINTERLACE_MODE_I4O2 && msg->lcdc_path_en) { IEP_ERR("Contradiction between dpi enable and deinterlace mode i4o2\n"); break; } switch (yuv_dil->dil_mode) { case IEP_DEINTERLACE_MODE_I4O2: if (dst1 == NULL) { IEP_ERR("Invalidate parameter!\n"); goto err; } else if (!g_mode && (dst1->act_w != msg->dst.act_w || dst1->act_h != msg->dst.act_h)) { IEP_ERR("Invalidate parameter, contradiction between two destination image size!\n"); goto err; } case IEP_DEINTERLACE_MODE_I4O1: if (src1 == NULL) { IEP_ERR("Invalidate parameter!\n"); goto err; } else if (!g_mode && (src1->act_w != msg->src.act_w || src1->act_h != msg->src.act_h)) { IEP_ERR("Invalidate parameter, contradiction between two source image size!\n"); goto err; } case IEP_DEINTERLACE_MODE_I2O1: if (msg->src.act_w > 1920) { goto err; } break; default: ; } return 0; } while (0); err: return -1; } int iep_api::direct_lcdc_path_sanity_check(iep_param_direct_path_interface_t *dpi) { do { int fmt; if (dpi == NULL) { IEP_ERR("Invalid parameter\n"); break; } if (msg->dein_mode == IEP_DEINTERLACE_MODE_I4O2) { IEP_ERR("Contradiction between dpi enable and deinterlace mode i4o2\n"); break; } fmt = msg->dst.format; switch (fmt) { case IEP_FORMAT_YCbCr_422_P: case IEP_FORMAT_YCrCb_422_SP: case IEP_FORMAT_YCrCb_422_P: case IEP_FORMAT_YCrCb_420_SP: case IEP_FORMAT_YCbCr_420_P: case IEP_FORMAT_YCrCb_420_P: case IEP_FORMAT_RGBA_8888: case IEP_FORMAT_BGR_565: IEP_ERR("Contradiction between dpi and destination format\n"); break; default: return 0; } } while (0); return -1; } int iep_api::init_sanity_check(iep_img *src, iep_img *dst) { do { int scl_fct_v, scl_fct_h; if (src == NULL || dst == NULL) { IEP_ERR("Invalidate parameter!\n"); break; } if ((src->format > 0x05 && src->format < 0x10) || src->format > 0x17) { IEP_ERR("Invalidate parameter, i/o format!\n"); break; } if (src->act_w > 4096 || src->act_h > 8192) { IEP_ERR("Invalidate parameter, source image size!\n"); break; } if (dst->act_w > 4096 || dst->act_h > 4096) { IEP_ERR("Invalidate parameter, destination image size!\n"); break; } scl_fct_h = src->act_w > dst->act_w ? (src->act_w * 1000 / dst->act_w) : (dst->act_w * 1000 / src->act_w); scl_fct_v = src->act_h > dst->act_h ? (src->act_h * 1000 / dst->act_h) : (dst->act_h * 1000 / src->act_h); if (scl_fct_h > 16000 || scl_fct_v > 16000) { IEP_ERR("Invalidate parameter, scale factor!\n"); break; } return 0; } while (0); return -1; } struct IEP_CAP* iep_api::query() { return ∩ } IEP_QUERY_INTERLACE iep_api::query_interlace() { if (cap.i4_deinterlace_supported) { return IEP_QUERY_INTERLACE_FULL_FUNC; } else if (cap.i2_deinterlace_supported) { return IEP_QUERY_INTERLACE_I2O1_ONLY; } else { return IEP_QUERY_INTERLACE_UNSUPPORTED; } } IEP_QUERY_DIMENSION iep_api::query_dimension() { if (cap.max_dynamic_width > 1920) { return IEP_QUERY_DIMENSION_4096; } else { return IEP_QUERY_DIMENSION_1920; } } iep_interface* iep_interface::create_new() { return new iep_api(); } void iep_interface::reclaim(iep_interface *iep_inf) { if (iep_inf) { delete iep_inf; iep_inf = NULL; } } iep_interface* iep_interface_create_new() { return iep_interface::create_new(); } void iep_interface_reclaim(iep_interface *iep_inf) { iep_interface::reclaim(iep_inf); } extern "C" void* iep_ops_claim() { return iep_interface::create_new(); } extern "C" int iep_ops_init(void *iep_obj, iep_img *src, iep_img *dst) { return ((iep_interface*)iep_obj)->init(src, dst); } extern "C" int iep_ops_init_discrete(void *iep_obj, int32_t src_act_w, int32_t src_act_h, int32_t src_x_off, int32_t src_y_off, int32_t src_vir_w, int32_t src_vir_h, int32_t src_format, uint32_t src_mem_addr, uint32_t src_uv_addr, uint32_t src_v_addr, int32_t dst_act_w, int32_t dst_act_h, int32_t dst_x_off, int32_t dst_y_off, int32_t dst_vir_w, int32_t dst_vir_h, int32_t dst_format, uint32_t dst_mem_addr, uint32_t dst_uv_addr, uint32_t dst_v_addr) { iep_img src; iep_img dst; src.act_w = src_act_w; src.act_h = src_act_h; src.x_off = src_x_off; src.y_off = src_y_off; src.vir_w = src_vir_w; src.vir_h = src_vir_h; src.format = src_format; src.mem_addr = src_mem_addr; src.uv_addr = src_uv_addr; src.v_addr = src_v_addr; dst.act_w = dst_act_w; dst.act_h = dst_act_h; dst.x_off = dst_x_off; dst.y_off = dst_y_off; dst.vir_w = dst_vir_w; dst.vir_h = dst_vir_h; dst.format = dst_format; dst.mem_addr = dst_mem_addr; dst.uv_addr = dst_uv_addr; dst.v_addr = dst_v_addr; ALOGE("%s, (%d, %d), (%d, %d), (%d, %d), %d, %x, %x, %x\n", __func__, src.act_w, src.act_h, src.x_off, src.y_off, src.vir_w, src.vir_h, src.format, src.mem_addr, src.uv_addr, src.v_addr); ALOGE("%s, (%d, %d), (%d, %d), (%d, %d), %d, %x, %x, %x\n", __func__, dst.act_w, dst.act_h, dst.x_off, dst.y_off, dst.vir_w, dst.vir_h, dst.format, dst.mem_addr, dst.uv_addr, dst.v_addr); return ((iep_interface*)iep_obj)->init(&src, &dst); } extern "C" int iep_ops_config_src_dst(void *iep_obj, iep_img *src, iep_img *dst) { return ((iep_interface*)iep_obj)->config_src_dst(src, dst); } extern "C" int iep_ops_config_yuv_enh(void *iep_obj) { return ((iep_interface*)iep_obj)->config_yuv_enh(); } extern "C" int iep_ops_config_yuv_enh_param(void *iep_obj, iep_param_YUV_color_enhance_t *yuv_enh) { return ((iep_interface*)iep_obj)->config_yuv_enh(yuv_enh); } extern "C" int iep_ops_config_color_enh(void *iep_obj) { return ((iep_interface*)iep_obj)->config_color_enh(); } extern "C" int iep_ops_config_color_enh_param(void *iep_obj, iep_param_RGB_color_enhance_t *rgb_enh) { return ((iep_interface*)iep_obj)->config_color_enh(rgb_enh); } extern "C" int iep_ops_config_scale(void *iep_obj) { return ((iep_interface*)iep_obj)->config_scale(); } extern "C" int iep_ops_config_scale_param(void *iep_obj, iep_param_scale_t *scale) { return ((iep_interface*)iep_obj)->config_scale(scale); } extern "C" int iep_ops_config_yuv_denoise(void *iep_obj) { return ((iep_interface*)iep_obj)->config_yuv_denoise(); } extern "C" int iep_ops_config_yuv_deinterlace(void *iep_obj) { return ((iep_interface*)iep_obj)->config_yuv_deinterlace(); } extern "C" int iep_ops_config_yuv_deinterlace_param1(void *iep_obj, iep_param_yuv_deinterlace_t *yuv_dil) { return ((iep_interface*)iep_obj)->config_yuv_deinterlace(yuv_dil); } extern "C" int iep_ops_config_yuv_dil_src_dst(void *iep_obj, iep_img *src1, iep_img *dst1) { return ((iep_interface*)iep_obj)->config_yuv_dil_src_dst(src1, dst1); } extern "C" int iep_ops_config_yuv_deinterlace_param2(void *iep_obj, iep_param_yuv_deinterlace_t *yuv_dil, iep_img *src1, iep_img *dst1) { return ((iep_interface*)iep_obj)->config_yuv_deinterlace(yuv_dil, src1, dst1); } extern "C" int iep_ops_config_color_space_convertion(void *iep_obj) { return ((iep_interface*)iep_obj)->config_color_space_convertion(); } extern "C" int iep_ops_config_color_space_convertion_param(void *iep_obj, iep_param_color_space_convertion_t *clr_convert) { return ((iep_interface*)iep_obj)->config_color_space_convertion(clr_convert); } extern "C" int iep_ops_config_direct_lcdc_path(void *iep_obj, iep_param_direct_path_interface_t *dpi) { return ((iep_interface*)iep_obj)->config_direct_lcdc_path(dpi); } extern "C" int iep_ops_run_sync(void *iep_obj) { return ((iep_interface*)iep_obj)->run_sync(); } extern "C" int iep_ops_run_async_ncb(void *iep_obj) { return ((iep_interface*)iep_obj)->run_async(NULL); } extern "C" int iep_ops_run_async(void *iep_obj, iep_notify notify) { return ((iep_interface*)iep_obj)->run_async(notify); } extern "C" int iep_ops_poll(void *iep_obj) { return ((iep_interface*)iep_obj)->poll(); } extern "C" void iep_ops_reclaim(void *iep_obj) { iep_interface::reclaim((iep_interface*)iep_obj); } struct iep_ops* alloc_iep_ops() { struct iep_ops *ops = (struct iep_ops*)malloc(sizeof(struct iep_ops)); if (ops == NULL) { IEP_ERR("allocate structure iep_ops failure\n"); return NULL; } ops->claim = iep_ops_claim; ops->init = iep_ops_init; ops->config_src_dst = iep_ops_config_src_dst; ops->config_yuv_enh = iep_ops_config_yuv_enh; ops->config_yuv_enh_param = iep_ops_config_yuv_enh_param; ops->config_color_enh = iep_ops_config_color_enh; ops->config_color_enh_param = iep_ops_config_color_enh_param; ops->config_scale = iep_ops_config_scale; ops->config_scale_param = iep_ops_config_scale_param; ops->config_yuv_denoise = iep_ops_config_yuv_denoise; ops->config_yuv_deinterlace = iep_ops_config_yuv_deinterlace; ops->config_yuv_deinterlace_param1 = iep_ops_config_yuv_deinterlace_param1; ops->config_yuv_dil_src_dst = iep_ops_config_yuv_dil_src_dst; ops->config_yuv_deinterlace_param2 = iep_ops_config_yuv_deinterlace_param2; ops->config_color_space_convertion = iep_ops_config_color_space_convertion; ops->config_color_space_convertion_param = iep_ops_config_color_space_convertion_param; ops->config_direct_lcdc_path = iep_ops_config_direct_lcdc_path; ops->run_sync = iep_ops_run_sync; ops->run_async = iep_ops_run_async; ops->poll = iep_ops_poll; ops->reclaim = iep_ops_reclaim; return ops; } void free_iep_ops(struct iep_ops *ops) { if (ops != NULL) { free(ops); } }