/* SPDX-License-Identifier: Apache-2.0 OR MIT */ /* * Copyright (c) 2018 Rockchip Electronics Co., Ltd. */ #define MODULE_TAG "iep_test" #include #include "mpp_mem.h" #include "mpp_time.h" #include "mpp_debug.h" #include "mpp_common.h" #include "mpp_thread.h" #include "mpp_buffer.h" #include "iep_api.h" #include "utils.h" #include "iniparser.h" #define MAX_URL_LEN (100) #define ADD_OFFSET(base, offset) ((RK_U32)base + ((RK_U32)(offset) << 10)) typedef enum { TEST_CASE_NONE, TEST_CASE_DEINTERLACE, TEST_CASE_YUVENHANCE, TEST_CASE_RGBENHANCE, } TEST_CASE; typedef struct IepTestCfg_t { RK_S32 src_w; RK_S32 src_h; RK_S32 src_fmt; RK_S32 dst_w; RK_S32 dst_h; RK_S32 dst_fmt; char src_url[MAX_URL_LEN]; char dst_url[MAX_URL_LEN]; char cfg_url[MAX_URL_LEN]; FILE *fp_src; FILE *fp_dst; TEST_CASE mode; dictionary *ini; IepCmdParamDeiCfg *dei_cfg; IepCmdParamYuvEnhance *yuv_enh; IepCmdParamRgbEnhance *rgb_enh; IepCmdParamColorConvert *colorcvt; } IepTestCfg; typedef struct IepTestInfo_t { IepTestCfg *cfg; size_t src_size; size_t dst_size; RK_U32 phy_src0; RK_U32 phy_src1; RK_U32 phy_dst0; RK_U32 phy_dst1; RK_U8 *vir_src0; RK_U8 *vir_src1; RK_U8 *vir_dst0; RK_U8 *vir_dst1; IepImg src; IepImg dst; IepCtx ctx; } IepTestInfo; static void parse_cfg(IepTestCfg *cfg) { dictionary *ini = cfg->ini; cfg->dei_cfg = mpp_calloc(IepCmdParamDeiCfg, 1); if (iniparser_find_entry(ini, "deinterlace")) { mpp_assert(cfg->dei_cfg); cfg->dei_cfg->dei_high_freq_en = iniparser_getint(ini, "deinterlace:high_freq_en", 0); cfg->dei_cfg->dei_mode = (IepDeiMode)iniparser_getint(ini, "deinterlace:dei_mode", 0); cfg->dei_cfg->dei_high_freq_fct = iniparser_getint(ini, "deinterlace:dei_high_freq_fct", 0); cfg->dei_cfg->dei_ei_mode = iniparser_getint(ini, "deinterlace:dei_ei_mode", 0); cfg->dei_cfg->dei_ei_smooth = iniparser_getint(ini, "deinterlace:dei_ei_smooth", 0); cfg->dei_cfg->dei_ei_sel = iniparser_getint(ini, "deinterlace:dei_ei_sel", 0); cfg->dei_cfg->dei_ei_radius = iniparser_getint(ini, "deinterlace:dei_ei_radius", 0); } else { cfg->dei_cfg->dei_high_freq_en = 1; cfg->dei_cfg->dei_mode = IEP_DEI_MODE_I4O1; cfg->dei_cfg->dei_field_order = IEP_DEI_FLD_ORDER_BOT_FIRST; cfg->dei_cfg->dei_ei_mode = 0; cfg->dei_cfg->dei_ei_smooth = 0; cfg->dei_cfg->dei_ei_sel = 0; cfg->dei_cfg->dei_ei_radius = 0; } if (iniparser_find_entry(ini, "yuv enhance")) { cfg->yuv_enh = mpp_calloc(IepCmdParamYuvEnhance, 1); cfg->yuv_enh->saturation = iniparser_getint(ini, "yuv enhance:saturation", 0); cfg->yuv_enh->contrast = iniparser_getint(ini, "yuv enhance:contrast", 0); cfg->yuv_enh->brightness = iniparser_getint(ini, "yuv enhance:brightness", 0); cfg->yuv_enh->hue_angle = iniparser_getint(ini, "yuv enhance:hue_angle", 0); cfg->yuv_enh->video_mode = (IepVideoMode) iniparser_getint(ini, "yuv enhance:video_mode", 0); cfg->yuv_enh->color_bar_y = iniparser_getint(ini, "yuv enhance:color_bar_y", 0); cfg->yuv_enh->color_bar_u = iniparser_getint(ini, "yuv enhance:color_bar_u", 0); cfg->yuv_enh->color_bar_v = iniparser_getint(ini, "yuv enhance:color_bar_v", 0); } if (iniparser_find_entry(ini, "rgb enhance")) { cfg->rgb_enh = mpp_calloc(IepCmdParamRgbEnhance, 1); cfg->rgb_enh->coe = iniparser_getint(ini, "rgb enhance:coe", 0); cfg->rgb_enh->mode = (IepRgbEnhanceMode) iniparser_getint(ini, "rgb enhance:mode", 0); cfg->rgb_enh->cg_en = iniparser_getint(ini, "rgb enhance:cg_en", 0); cfg->rgb_enh->cg_rr = iniparser_getint(ini, "rgb enhance:cg_rr", 0); cfg->rgb_enh->cg_rg = iniparser_getint(ini, "rgb enhance:cg_rg", 0); cfg->rgb_enh->cg_rb = iniparser_getint(ini, "rgb enhance:cg_rb", 0); cfg->rgb_enh->order = (IepRgbEnhanceOrder) iniparser_getint(ini, "rgb enhance:order", 0); cfg->rgb_enh->threshold = iniparser_getint(ini, "rgb enhance:threshold", 0); cfg->rgb_enh->alpha_num = iniparser_getint(ini, "rgb enhance:alpha_num", 0); cfg->rgb_enh->alpha_base = iniparser_getint(ini, "rgb enhance:alpha_base", 0); cfg->rgb_enh->radius = iniparser_getint(ini, "rgb enhance:radius", 0); } if (iniparser_find_entry(ini, "colorcvt")) { cfg->colorcvt = mpp_calloc(IepCmdParamColorConvert, 1); cfg->colorcvt->rgb2yuv_mode = (IepColorConvertMode) iniparser_getint(ini, "colorcvt:rgb2yuv_mode", 0); cfg->colorcvt->yuv2rgb_mode = (IepColorConvertMode) iniparser_getint(ini, "colorcvt:yuv2rgb_mode", 0); cfg->colorcvt->rgb2yuv_input_clip = iniparser_getint(ini, "colorcvt:rgb2yuv_input_clip", 0); cfg->colorcvt->yuv2rgb_input_clip = iniparser_getint(ini, "colorcvt:yuv2rgb_input_clip", 0); cfg->colorcvt->global_alpha_value = iniparser_getint(ini, "colorcvt:global_alpha_value", 0); cfg->colorcvt->dither_up_en = iniparser_getint(ini, "colorcvt:dither_up_en", 0); cfg->colorcvt->dither_down_en = iniparser_getint(ini, "colorcvt:dither_down_en", 0); } } static RK_S32 get_image_size(RK_S32 w, RK_S32 h, RK_S32 fmt) { RK_S32 img_size = 0; switch (fmt) { case IEP_FORMAT_ABGR_8888: case IEP_FORMAT_ARGB_8888: case IEP_FORMAT_BGRA_8888: case IEP_FORMAT_RGBA_8888: img_size = w * h * 4; break; case IEP_FORMAT_BGR_565: case IEP_FORMAT_RGB_565: case IEP_FORMAT_YCbCr_422_P: case IEP_FORMAT_YCbCr_422_SP: case IEP_FORMAT_YCrCb_422_P: case IEP_FORMAT_YCrCb_422_SP: img_size = w * h * 2; break; case IEP_FORMAT_YCbCr_420_P: case IEP_FORMAT_YCbCr_420_SP: case IEP_FORMAT_YCrCb_420_P: case IEP_FORMAT_YCrCb_420_SP: img_size = w * h * 3 / 2; break; default : { } break; } return img_size; } static void config_iep_img(IepImg *img, RK_S32 w, RK_S32 h, RK_S32 fmt, RK_U32 base) { switch (fmt) { case IEP_FORMAT_ABGR_8888: case IEP_FORMAT_ARGB_8888: case IEP_FORMAT_BGRA_8888: case IEP_FORMAT_RGBA_8888: img->v_addr = 0; break; case IEP_FORMAT_BGR_565: case IEP_FORMAT_RGB_565: case IEP_FORMAT_YCbCr_422_P: case IEP_FORMAT_YCbCr_422_SP: case IEP_FORMAT_YCrCb_422_P: case IEP_FORMAT_YCrCb_422_SP: img->v_addr = ADD_OFFSET(base, w * h + w * h / 2); break; case IEP_FORMAT_YCbCr_420_P: case IEP_FORMAT_YCbCr_420_SP: case IEP_FORMAT_YCrCb_420_P: case IEP_FORMAT_YCrCb_420_SP: img->v_addr = ADD_OFFSET(base, w * h + w * h / 4); break; default : { } break; } img->act_w = w; img->act_h = h; img->x_off = 0; img->y_off = 0; img->vir_w = w; img->vir_h = h; img->format = fmt; img->mem_addr = base; img->uv_addr = ADD_OFFSET(base, w * h); } void* iep_process_thread(void *param) { IepTestInfo *info = (IepTestInfo*)param; IepTestCfg *cfg = info->cfg; config_iep_img(&info->src, cfg->src_w, cfg->src_h, cfg->src_fmt, info->phy_src0); config_iep_img(&info->dst, cfg->dst_w, cfg->dst_h, cfg->dst_fmt, info->phy_dst0); if (info->src_size > fread(info->vir_src0, 1, info->src_size, cfg->fp_src)) { mpp_err("read file failed\n"); return NULL; } iep_control(info->ctx, IEP_CMD_INIT, NULL); iep_control(info->ctx, IEP_CMD_SET_SRC, &info->src); iep_control(info->ctx, IEP_CMD_SET_DST, &info->dst); switch (cfg->mode) { case TEST_CASE_YUVENHANCE: { iep_control(info->ctx, IEP_CMD_SET_YUV_ENHANCE, cfg->yuv_enh); } break; case TEST_CASE_RGBENHANCE: { iep_control(info->ctx, IEP_CMD_SET_RGB_ENHANCE, cfg->rgb_enh); } break; case TEST_CASE_DEINTERLACE: { IepImg src1; IepImg dst1; if (info->src_size != fread(info->vir_src1, 1, info->src_size, cfg->fp_src)) mpp_err("failed to read %d from input\n", info->src_size); config_iep_img(&src1, cfg->src_w, cfg->src_h, cfg->src_fmt, info->phy_src1); config_iep_img(&dst1, cfg->src_w, cfg->src_h, cfg->src_fmt, info->phy_dst1); iep_control(info->ctx, IEP_CMD_SET_DEI_SRC1, &src1); iep_control(info->ctx, IEP_CMD_SET_DEI_DST1, &dst1); iep_control(info->ctx, IEP_CMD_SET_DEI_CFG, cfg->dei_cfg); } break; default: { } break; } RK_S64 intime = mpp_time(); if (0 == iep_control(info->ctx, IEP_CMD_RUN_SYNC, NULL)) mpp_log("%d success\n", getpid()); else mpp_log("%d failure\n", getpid()); mpp_log("%s consume %lld ms\n", __func__, (mpp_time() - intime) / 1000); if (cfg->fp_dst) fwrite(info->vir_dst0, 1, info->dst_size, cfg->fp_dst); return NULL; } static RK_S32 str_to_iep_fmt(const char *str) { RK_S32 fmt = -1; if (!strcmp(str, "argb8888")) fmt = IEP_FORMAT_ARGB_8888; else if (!strcmp(str, "abgr8888")) fmt = IEP_FORMAT_ABGR_8888; else if (!strcmp(str, "rgba8888")) fmt = IEP_FORMAT_BGRA_8888; else if (!strcmp(str, "bgra8888")) fmt = IEP_FORMAT_BGRA_8888; else if (!strcmp(str, "rgb565")) fmt = IEP_FORMAT_RGB_565; else if (!strcmp(str, "bgr565")) fmt = IEP_FORMAT_BGR_565; else if (!strcmp(str, "yuv422sp")) fmt = IEP_FORMAT_YCbCr_422_SP; else if (!strcmp(str, "yuv422p")) fmt = IEP_FORMAT_YCbCr_422_P; else if (!strcmp(str, "yuv420sp")) fmt = IEP_FORMAT_YCbCr_420_SP; else if (!strcmp(str, "yuv420p")) fmt = IEP_FORMAT_YCbCr_420_P; else if (!strcmp(str, "yvu422sp")) fmt = IEP_FORMAT_YCrCb_422_SP; else if (!strcmp(str, "yvu422p")) fmt = IEP_FORMAT_YCrCb_422_P; else if (!strcmp(str, "yvu420sp")) fmt = IEP_FORMAT_YCrCb_420_SP; else if (!strcmp(str, "yvu420p")) fmt = IEP_FORMAT_YCrCb_420_P; else mpp_err("invalid format %s\n", str); return fmt; } static MPP_RET check_input_cmd(IepTestCfg *cfg) { MPP_RET ret = MPP_OK; if (cfg->src_w <= 0) { mpp_err("non-positive input width %d\n", cfg->src_w); ret = MPP_NOK; } if (cfg->src_h <= 0) { mpp_err("non-positive input height %d\n", cfg->src_h); ret = MPP_NOK; } if (cfg->src_fmt < IEP_FORMAT_ARGB_8888 || cfg->src_fmt > IEP_FORMAT_YCrCb_420_P) { mpp_err("invalid input format\n"); ret = MPP_NOK; } if (cfg->fp_src == NULL) { mpp_err("failed to open input file %s\n", cfg->src_url); ret = MPP_NOK; } if (cfg->dst_w <= 0) { mpp_err("non-positive input width %d\n", cfg->dst_w); ret = MPP_NOK; } if (cfg->dst_h <= 0) { mpp_err("non-positive input height %d\n", cfg->dst_h); ret = MPP_NOK; } if (cfg->dst_fmt < IEP_FORMAT_ARGB_8888 || cfg->dst_fmt > IEP_FORMAT_YCrCb_420_P) { mpp_err("invalid input format\n"); ret = MPP_NOK; } if (cfg->mode == TEST_CASE_NONE) { mpp_err("invalid work mode\n"); ret = MPP_NOK; } return ret; } static OptionInfo iep_test_cmd[] = { {"w", "src_width", "input image width"}, {"h", "src_height", "input image height"}, {"c", "src_format", "input image format in ASCII string"}, {"f", "src_file", "input image file name"}, {"W", "dst_width", "output image width"}, {"H", "dst_height", "output image height"}, {"C", "dst_format", "output image format in ASCII string"}, {"F", "dst_file", "output image file name"}, {"m", "work_mode", "working mode of iep in ASCII string"}, {"x", "configure", "configure file of working mode"}, }; static void iep_test_help() { mpp_log("usage: iep_test [options]\n"); mpp_log("*******************************\n"); show_options(iep_test_cmd); mpp_log("*******************************\n"); mpp_log("supported ASCII format strings:\n"); mpp_log(" 0 - argb8888\n"); mpp_log(" 1 - abgr8888\n"); mpp_log(" 2 - rgba8888\n"); mpp_log(" 3 - bgra8888\n"); mpp_log(" 4 - rgb565\n"); mpp_log(" 5 - bgr565\n"); mpp_log(" 6 - yuv422sp\n"); mpp_log(" 7 - yuv422p\n"); mpp_log(" 8 - yuv420sp\n"); mpp_log(" 9 - yuv420p\n"); mpp_log("10 - yvu422sp\n"); mpp_log("11 - yvu422p\n"); mpp_log("12 - yvu420sp\n"); mpp_log("13 - yvu420p\n"); mpp_log("*******************************\n"); mpp_log("supported work mode strings:\n"); mpp_log(" 1 - deinterlace\n"); mpp_log(" 2 - yuvenhance\n"); mpp_log(" 3 - rgbenhance\n"); mpp_log("************ sample ***********\n"); mpp_log("iep_test -w 720 -h 480 -c yuv420p -f input.yuv -W 720 -H 480 -C yuv420p -F output.yuv -m deinterlace -x dil.cfg\n"); } int main(int argc, char **argv) { IepTestCfg cfg; IepTestInfo info; int ch; if (argc < 2) { iep_test_help(); return 0; } memset(&cfg, 0, sizeof(cfg)); memset(&info, 0, sizeof(info)); cfg.src_fmt = IEP_FORMAT_YCbCr_420_SP; cfg.dst_fmt = IEP_FORMAT_YCbCr_420_SP; /// get options opterr = 0; while ((ch = getopt(argc, argv, "f:w:h:c:F:W:H:C:m:x:")) != -1) { switch (ch) { case 'w': { cfg.src_w = atoi(optarg); } break; case 'h': { cfg.src_h = atoi(optarg); } break; case 'c': { cfg.src_fmt = str_to_iep_fmt(optarg); } break; case 'W': { cfg.dst_w = atoi(optarg); } break; case 'H': { cfg.dst_h = atoi(optarg); } break; case 'C': { cfg.dst_fmt = str_to_iep_fmt(optarg); } break; case 'f': { mpp_log("input filename: %s\n", optarg); strncpy(cfg.src_url, optarg, sizeof(cfg.src_url) - 1); cfg.fp_src = fopen(cfg.src_url, "rb"); } break; case 'F': { mpp_log("output filename: %s\n", optarg); strncpy(cfg.dst_url, optarg, sizeof(cfg.dst_url) - 1); cfg.fp_dst = fopen(cfg.dst_url, "w+b"); } break; case 'm': { if (!strcmp(optarg, "deinterlace")) { cfg.mode = TEST_CASE_DEINTERLACE; } else if (!strcmp(optarg, "yuvenhance")) { cfg.mode = TEST_CASE_YUVENHANCE; } else if (!strcmp(optarg, "rgbenhance")) { cfg.mode = TEST_CASE_RGBENHANCE; } else { mpp_err("invalid work mode %s\n", optarg); cfg.mode = TEST_CASE_NONE; } } break; case 'x': { mpp_log("configure filename: %s\n", optarg); strncpy(cfg.cfg_url, optarg, sizeof(cfg.cfg_url) - 1); cfg.ini = iniparser_load(cfg.cfg_url); if (cfg.ini) parse_cfg(&cfg); else mpp_err("invalid configure file %s\n", optarg); } break; default: { } break; } } if (check_input_cmd(&cfg)) { mpp_err("failed to pass cmd line check\n"); iep_test_help(); return -1; } info.cfg = &cfg; info.src_size = get_image_size(cfg.src_w, cfg.src_h, cfg.src_fmt); info.dst_size = get_image_size(cfg.dst_w, cfg.dst_h, cfg.dst_fmt); // allocate 12M in/out memory and initialize memory address MppBuffer buffer = NULL; size_t src_size = MPP_ALIGN(info.src_size, SZ_4K); size_t dst_size = MPP_ALIGN(info.dst_size, SZ_4K); // NOTE: deinterlace need 4 fields (2 frames) as input and output 2 frames size_t total_size = src_size * 2 + dst_size * 2; mpp_buffer_get(NULL, &buffer, total_size); mpp_assert(buffer); int buf_fd = mpp_buffer_get_fd(buffer); RK_U8 *buf_ptr = (RK_U8 *)mpp_buffer_get_ptr(buffer); memset(buf_ptr, 0xff, total_size); info.phy_src0 = ADD_OFFSET(buf_fd, 0); info.phy_src1 = ADD_OFFSET(buf_fd, src_size); info.phy_dst0 = ADD_OFFSET(buf_fd, src_size * 2); info.phy_dst1 = ADD_OFFSET(buf_fd, src_size * 2 + dst_size); info.vir_src0 = buf_ptr; info.vir_src1 = buf_ptr + src_size; info.vir_dst0 = buf_ptr + src_size * 2; info.vir_dst1 = buf_ptr + src_size * 2 + dst_size; iep_init(&info.ctx); pthread_t td; pthread_create(&td, NULL, iep_process_thread, &info); pthread_join(td, NULL); if (info.ctx) { iep_deinit(info.ctx); info.ctx = NULL; } if (cfg.fp_src) { fclose(cfg.fp_src); cfg.fp_src = NULL; } if (cfg.fp_dst) { fclose(cfg.fp_dst); cfg.fp_dst = NULL; } if (cfg.ini) { iniparser_freedict(cfg.ini); cfg.ini = NULL; if (cfg.yuv_enh) mpp_free(cfg.yuv_enh); if (cfg.rgb_enh) mpp_free(cfg.rgb_enh); if (cfg.dei_cfg) mpp_free(cfg.dei_cfg); if (cfg.colorcvt) mpp_free(cfg.colorcvt); } mpp_buffer_put(buffer); return 0; }