MI IQSERVER API


REVISION HISTORY

Revision No.
Description
Date
3.0
  • Initial release
  • 12/04/2020
    3.1
  • Add note in SetDataPath
  • 04/09/2024

    1. OVERVIEW


    1.1. Module Description

    IQSERVER (Image Quality tuning Server) is used for data transport between tuning tool (IQ Tool) and EVB, including ISP parameter setting, image capture and file upload/download.


    1.2. Basic Structure

    • ISP

      Image Signal Processing, used for image noise reduction, color rendering, brightness adjustment, and other functions.

    • SCL

      Scale.

    • VENC

      Video Encoder, used for encoding YUV stream to H264/H265/Jpeg format bit-stream.


    1.3. Basic Structure

    MI_IQSERVER supports the following functions:

    • Support IQ and ISP parameter settings.
    • Support capture of raw/yuv/jpg/raw stream.

    1.4. Application scenarios

    IQSERVER can be applied to the following scenarios:

    1. Pure linux scenario

      In the linux environment, NetWork and IQTool connection debugging are supported.

    2. Pure rtos scenario

      In the rtos environment, UVC and IQTool connection debugging are supported.

    3. Dualos scenario

      In the dualos environment, NetWork and IQTool connection debugging are supported.


    1.5. Working Principle

    IQSERVER has two calling methods:

    • The first is the interactive process of Network:

    • The second is the interactive process of UVC (this process is not supported by Pcupid yet):


    1.6. Development process

    1. Enter the alkaid project root directory, make menuconfig

    2. Press Enter to enter the Sdk Config sub-option

    3. Press Enter to enter the Interface Compile Config sub-option

    4. Press the spacebar to select the iqserver sub-module and recompile the project

      After the compilation is completed, libmi_iqserver.a will be generated under sdk/interface/src/iqserver


    1.7. Example Introduction

    Take vif_isp_scl streaming demo as an example

    • You need to import iqserver lib in demo's makefile
      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;
    }
    

    Note: The actual part of the above example for users is to call MI_IQSERVER_Open() after the streaming is completed and call MI_IQSERVER_Close() after the streaming is closed. The rest are the streaming process of MI_demo.


    2. API LIST

    This function module provides the following APIs.

    API Name Function
    MI_IQSERVER_Open Open IQ server
    MI_IQSERVER_Close Close IQ server
    MI_IQSERVER_SetDataPath Set IQ server data path
    MI_IQSERVER_SetCustFunc Set user specified execute function

    2.1. MI_IQSERVER_Open

    • Function

      Call this interface to open IQ server.

    • Syntax

      MI_S32 MI_IQSERVER_Open();
      
    • Return Value

      • MI_IQSERVER_OK: Successful

      • Others: Failed, see error code for details.

    • Dependency

      • Head file: mi_iqserver.h

      • Others: libmi_iqserver.a

    • Note

      • IQ server can only be called once
      • IQ server must be in the same process as the ISP streaming process
      • The default port of IQ server is 9876
    • Example

      /*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;
      
      }
      
    • Related APIs

      MI_IQSERVER_Close


    2.2. MI_IQSERVER_Close

    • Function

      Call this interface to close IQ server.

    • Syntax

      MI_ S32 MI_IQSERVER_Close();
      
    • Return Value

      • MI_IQSERVER_OK: Successful.

      • Others: Failed, see error code for details.

    • Dependency

      • Head file: mi_iqserver.h

      • Library file: libmi_iqserver.a

    • Note

      The number of calls for MI_IQSERVER_Open and MI_IQSERVER_Close must correspond.

    • Example

      /*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;
      
      }
      
    • Related APIs

      MI_IQSERVER_Open


    2.3. MI_IQSERVER_SetDataPath

    • Function

      Set IQ server data path.

    • Syntax

      MI_S32 MI_IQSERVER_SetDataPath(char* path);
      
    • Form parameter

      Parameter Name Description Input/Output
      path Path of IQ server data, ending with \0. Input
    • Return Value

      • MI_IQSERVER_OK: Successful.

      • Others: Failed, see error code for details.

    • Dependency

      • Head file: mi_iqserver.h

      • Library file: libmi_iqserver.a

    • Note

      • You can call this API before MI_IQSERVER_Open.

      • Before calling this API, make sure that the path is accessible and that the data needed by the IQ server is available.

      • Normally, the data needed by the IQ server include isp_api.xml (for use by IQ Tool).

      • By default, isp_api.xml reads the /config/iqfile path, if it is not this path, you need to call the sub-interface to set it.
    • Example

      /*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

    • Function

      Set user-specified execute function, for IQ server to call it.

    • Syntax

      MI_S32 MI_IQSERVER_SetCustFunc(MI_S32(*func)(MI_U16 data_type,
      MI_U32 length, MI_U8 *data));
      
    • Form parameter

      Parameter Name Description Input/Output
      func Execute function Input
    • Return Value

      • MI_IQSERVER_OK: Successful.

      • Others: Failed, see error code for details.

    • Dependency

      • Head file: mi_iqserver.h

      • Library file: libmi_iqserver.a

    • Note

      • Before using this API, define the function with the parameters below:

        1. datatype: type of data, user defined, to distinguish different data.

        2. length: length of data, IQ tool will auto set the value.

        3. data: data address.

        You can do some processing in func with these parameters.

      • By this API, you can add user-defined execute function in IQ server. IQ server will get the data from IQ tool, then call the user-defined function. After that, func will get the data, to implement custom features.

        For example:

        1. Use IQ tool to write firmware, then IQ server calls func to flash firmware.

        2. Use IQ tool to set IR cut, then IQ server calls func to switch IR.

      • Before calling this function, make sure func is executable.

      • Data_type and data come from IQ tool, and length means data length.

      • Data_type can be used to distinguish what function the data is used for. You can define different function for different data.

    • Example

      /*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. ERROR CODE


    The IQSERVER API error code is as follows:

    Error Code Macro Definition Description
    0XA02C2000 MI_ERR_IQSERVER_NOMEM No memmory
    0XA02C2001 MI_ERR_IQSERVER_NOBUF No buffer
    0XA02C2002 MI_ERR_IQSERVER_CREATE_THREAD Null pointer
    0XA02C2003 MI_ERR_IQSERVER_INVALID_IQPATH Invalid IQ data path