MI IQSERVER API
REVISION HISTORY¶
Revision No. | Description |
Date |
---|---|---|
3.0 | 12/04/2020 | |
3.1 | 04/09/2024 |
1. 概述¶
1.1. 模块说明¶
IQSERVER(Image Quality tuning Server)图像质量调校服务,用来完成调校工具(IQTool)和开发板之间的数据通信,包括ISP参数设置,获取图像,上传/下载相关文件等功能。
1.2. 基本结构¶
-
ISP
Image Signal Processing 图像信号处理单元,负责图像降噪/颜色渲染/亮度调整等功能。
-
SCL
Scale(缩放)。
-
VENC
Video Encoder 视频编码器,负责将YUV序列编码成H264/H265/Jpeg等格式的视频流。
1.3. 功能介绍¶
MI_IQSERVER支持以下功能:
- 支持IQ与ISP的参数设置。
- 支持抓raw/yuv/jpg/raw stream。
1.4. 应用场景¶
IQSERVER可应用于以下场景:
-
Pure linux场景
在linux环境下,支持NetWork与IQTool连接调试。
-
Pure rtos场景
在rtos环境下,只支持UVC与IQTool连接调试。
-
Dualos场景
在dualos环境下,支持NetWork与IQTool连接调试。
1.5. 工作原理¶
IQSERVER有两种调用方式:
-
第一种是Network的交互流程:
-
第二种是UVC的交互流程(该流程Pcupid暂未支持):
1.6. 开发流程¶
-
进入alkaid project根目录,make menuconfig
-
回车键进入Sdk Config子选项
-
回车键进入Interface Compile Config子选项
-
空格键选中iqserver子模块,并重新编译project
编译完成将在sdk/interface/src/iqserver下生成 libmi_iqserver.a
1.7. 实例介绍¶
以vif_isp_scl串流demo为例
- 需要在demo的makefile中导入iqserver的lib
ifeq ($(PROG_ISPIQ_ENABLE), 1) INC += ./internal/cus3a LIBS += -lmi_iqserver -lcus3a -lispalgo ifeq ($(NIR_SUPPORT), 1) LIBS += -lmi_nir endif endif
void *ST_IQthread(void * args) { #if MI_ISPIQ_SUPPORT MI_ISP_DEV IspDevId = 0; MI_ISP_CHANNEL IspChnId = 0; char IqApiBinFilePath[ST_MAX_ISP_CHN_NUM][128]; MI_SNR_PADID ePADId; ST_Sensor_Attr_t* pstSensorAttr = NULL; memset(IqApiBinFilePath, 0, sizeof(char)*128*ST_MAX_ISP_CHN_NUM); MI_IQSERVER_Open(); while (!g_stIqResInfo.bThreadExit) { for(IspDevId=0; IspDevId<ST_MAX_ISP_DEV_NUM; IspDevId++) { ST_IspDevAttr_t *pstIspDevAttr= &gstIspModule.stIspDevAttr[IspDevId]; if(pstIspDevAttr->bUsed == TRUE && pstIspDevAttr->bCreate == TRUE) { for(IspChnId=0; IspChnId<ST_MAX_ISP_CHN_NUM; IspChnId++) { ST_IspChannelAttr_t *pstIspChnAttr = &pstIspDevAttr->stIspChnlAttr[IspChnId]; if(pstIspChnAttr->bUsed == TRUE && pstIspChnAttr->bCreate == TRUE) { MI_ISP_IQ_Nr3dType_t stNR3D; MI_ISP_IQ_ParamInitInfoType_t status; //MI_ISP_ChnParam_t stIspChnParam; MI_SNR_PlaneInfo_t stPlaneInfo; char IqApiBinFilePath_tmp[128]; MI_S32 s32ret = MI_SUCCESS; memset(&stNR3D,0x0,sizeof(MI_ISP_IQ_Nr3dType_t)); memset(&status,0x0,sizeof(MI_ISP_IQ_ParamInitInfoType_t)); //memset(&stIspChnParam,0x0,sizeof(MI_ISP_ChnParam_t)); memset(&stPlaneInfo,0x0,sizeof(MI_SNR_PlaneInfo_t)); memset(IqApiBinFilePath_tmp, 0, sizeof(char)*128); s32ret = MI_ISP_IQ_GetParaInitStatus(IspDevId,IspChnId, &status); if((s32ret == MI_SUCCESS && status.stParaAPI.bFlag != 1) || (s32ret != MI_SUCCESS)) { continue; } s32ret = MI_ISP_IQ_GetNr3d(IspDevId, IspChnId, &stNR3D); if(s32ret == MI_SUCCESS && stNR3D.bEnable == E_SS_IQ_FALSE) { stNR3D.bEnable = E_SS_IQ_TRUE; printf("SET ISP dev %d, chn %d,NR3D status:%d, type:%d\n",IspDevId, IspChnId,stNR3D.bEnable, stNR3D.enOpType); if(MI_SUCCESS != MI_ISP_IQ_SetNr3d(IspDevId, IspChnId, &stNR3D)) { DBG_ERR("isp dev%d chn%d set NR3D failed!! \n",IspDevId, IspChnId); } } //MI_ISP_GetChnParam(IspDevId, IspChnId, &stIspChnParam); ePADId = ST_GetFirstSensorPadId(pstIspChnAttr->u32SensorBindId); pstSensorAttr = &gstSensorAttr[ePADId]; if(ePADId < ST_MAX_SENSOR_NUM && bUseUserSensor == FALSE && pstSensorAttr->bCreate) { MI_SNR_GetPlaneInfo(ePADId, 0, &stPlaneInfo); sprintf(IqApiBinFilePath_tmp, "/config/iqfile/%s_api.bin", stPlaneInfo.s8SensorName); } if(pstIspChnAttr->IqCfgbin_Path[0] != '\0') { if(0!=strcmp(IqApiBinFilePath[IspChnId], pstIspChnAttr->IqCfgbin_Path)) { memcpy(IqApiBinFilePath[IspChnId], pstIspChnAttr->IqCfgbin_Path, sizeof(char)*128); printf("loading api bin...path:%s\n",IqApiBinFilePath[IspChnId]); MI_ISP_ApiCmdLoadBinFile(IspDevId, IspChnId, (char *)IqApiBinFilePath[IspChnId], 1234); } } else { if(0!=strcmp(IqApiBinFilePath[IspChnId], IqApiBinFilePath_tmp)) { memcpy(IqApiBinFilePath[IspChnId], IqApiBinFilePath_tmp, sizeof(char)*128); printf("loading api bin...path:%s\n",IqApiBinFilePath[IspChnId]); MI_ISP_ApiCmdLoadBinFile(IspDevId, IspChnId, (char *)IqApiBinFilePath[IspChnId], 1234); } } } } } } usleep(THREAD_SLEEP_TIME_US*10); } MI_IQSERVER_Close(); #endif return NULL; }
说明:以上实例对于使用者真正用到的部分是在串流完成之后调用MI_IQSERVER_Open()以及在串流关闭之后调用MI_IQSERVER_Close()即可,其余部分均为该MI_demo的串流流程。
2. API 参考¶
该功能模块提供以下 API:
API名 | 功能 |
---|---|
MI_IQSERVER_Open | 启动IQ server |
MI_IQSERVER_Close | 关闭IQ server |
MI_IQSERVER_SetDataPath | 设置IQ server数据存储路径 |
MI_IQSERVER_SetCustFunc | 设置IQ server的可执行自定义函数 |
2.1. MI_IQSERVER_Open¶
-
功能
调用此接口启动IQ server。
-
语法
MI_S32 MI_IQSERVER_Open();
-
返回值
-
MI_IQSERVER_OK, 启动IQ server成功。
-
其它, 启动失败,详情参照错误码。
-
-
依赖
-
头文件:mi_iqserver.h
-
库文件:libmi_iqserver.a
-
-
注意
- IQ server只能调用一次
- IQ server必须与ISP串流流程在同一个进程下
- IQ server默认端口为9876
-
举例
/*declaration*/ MI_S32 s32Ret = 0; /* open IQSERVER*/ s32Ret = MI_IQSERVER_Open(); if (MI_IQSERVER_OK != s32Ret) { Printf(“open iqserver error:%x\n”, s32Ret); return s32Ret; }
-
相关主题
2.2. MI_IQSERVER_Close¶
-
功能
调用此接口关闭IQ server。
-
语法
MI_ S32 MI_IQSERVER_Close();
-
返回值
-
MI_IQSERVER_OK,成功关闭IQ server。
-
其它, 关闭IQ server失败,详情参照错误码。
-
-
依赖
-
头文件:mi_iqserver.h
-
库文件:libmi_iqserver.a
-
-
注意
调用MI_IQSERVER_Open 与 MI_IQSERVER_Close 需要对应。
-
举例
/*declaration*/ MI_S32 s32Ret = 0; /* close IQSERVER*/ s32Ret = MI_IQSERVER_Close(); if (MI_IQSERVER_OK != s32Ret) { Printf(“close iqserver error:%x\n”, s32Ret); return s32Ret; }
-
相关主题
2.3. MI_IQSERVER_SetDataPath¶
-
功能
设置IQ server的数据存储路径。
-
语法
MI_S32 MI_IQSERVER_SetDataPath(char* path);
-
形参
参数名称 描述 输入/输出 path 路径字符串指针,末尾是\0。 输入 -
返回值
-
MI_IQSERVER_OK,成功。
-
其它,设置失败,详情参照错误码。
-
-
依赖
-
头文件:mi_iqserver.h
-
库文件:libmi_iqserver.a
-
-
注意
-
可以在MI_IQSERVER_Open 之前调用。
-
调用前,请确认路径是否可访问,路径内是否有IQ server需要的数据资料。
-
IQ server通常需要读取的资料有:isp_api.xml(用于IQ Tool使用)。
-
isp_api.xml默认读取的是/config/iqfile路径,如果不是这个路径,就需要调用这个接口进行设置。
-
-
举例
/*declaration*/ MI_S32 s32Ret = 0; char *data_path = “/customer/iqconfig/”; /* set IQSERVER data path*/ s32Ret = MI_IQSERVER_SetDataPath(data_path); if (MI_IQSERVER_OK != s32Ret) { Printf(“set iqserver data path error:%x\n”, s32Ret); return s32Ret; }
-
相关主题
无。
2.4. MI_IQSERVER_SetCustFunc¶
-
功能
设置IQ server的可执行的自定义函数,满足用户通过IQ Server调用自定义接口函数的目的。
-
语法
MI_S32 MI_IQSERVER_SetCustFunc(MI_S32(* func)(MI_U16 data_type, MI_U32 length, MI_U8 * data));
-
形参
参数名称 描述 输入/输出 func 用户自定义的函数指针 输入 -
返回值
-
MI_IQSERVER_OK,成功。
-
其它,设置失败,详情参照错误码。
-
-
依赖
-
头文件:mi_iqserver.h
-
库文件:libmi_iqserver.a
-
-
注意
-
使用前,需要用户先实现自定义的func函数。函数参数如下:
-
datatype: 表示data的类型,用户自定义,用来区分不同的data。
-
length: 表示data的长度,IQ Tool会识别并自动填入该值。
-
data: 表示data地址。
在func内部可根据上述参数,做相关处理。
-
-
可以添加用户自定义的函数功能实现, IQ server内部获取IQ Tool传入的数据,再调用用户传进来的函数func,这样在func里面就可以获取到IQ Tool的数据,实现客制化的功能。
比如下面两项自定义功能:
-
通过IQ Tool传入固件,在func里面获取固件,然后烧写flash。
-
通过IQ Tool传入IR开关选项,在func里面切换IR。
-
-
调用前,请确认函数指针func是否可执行。
-
Data_type和data数据通过IQ tool传入,length表示data的长度。
-
Data_type可以用来区分data的类型,这样func可以针对不同的类型实现不同的功能。
-
-
举例
/*declaration*/ MI_S32 s32Ret = 0; MI_S32 sample_func(MI_U16 data_type, MI_U32 length, MI_U8 *data) { printf("call MI_IQSERVER_SetCustFunc() success\n"); printf(“data_type is %d, length:%u, data addr:%p\n”, data_type, length, data); //do something return MI_IQSERVER_OK; } /* set IQSERVER custom function*/ s32Ret = MI_IQSERVER_SetCustFunc(sample_func); if (MI_IQSERVER_OK != s32Ret) { Printf(“set iqserver cust func error:%x\n”, s32Ret); return s32Ret; }
-
相关主题
无。
3. 错误码¶
IQSERVER API 错误码如下所示。
错误代码 | 宏定义 | 描述 |
---|---|---|
0XA02C2000 | MI_ERR_IQSERVER_NOMEM | 内存不足 |
0XA02C2001 | MI_ERR_IQSERVER_NOBUF | Buffer不够 |
0XA02C2002 | MI_ERR_IQSERVER_CREATE_THREAD | 线程创建失败 |
0XA02C2003 | MI_ERR_IQSERVER_INVALID_IQPATH | IQ数据路径非法 |