基於海思Hi3559V200的AWB/LSC OTP燒錄信息調用,並實現AWB/LSC 校正

這裏的OTP是用來給camera sensor做calibration(校準)用的。

因爲模組生產出來會有很大的差異性,爲了保證效果一致性,模組廠會挑選一部分模組作爲golden,然後將其他模組的相應參數校準到和這些golden一樣,(golden不是最好的模組,也不是最差的模組,而是各方面最平均的模組)

OTP燒錄的數據類型

一般包括:

AF:自動對焦校準數據
AWB:白平衡校準數據
LSC:鏡頭陰影校準 (Lens Shading Calibration)
Moudle Info:模組信息,包含模組的生產年日月,模組ID等

說明

OTP標定只針對shading和靜態白平衡做一下標定。
 
我們當前設計的靜態AWB OTP標定是這樣的:

1、客戶選出Golden後,用Golden完成AWB離線標定,得到靜態白平衡係數,普朗克曲線等標定結果。

2、用Golden在D50 Flat場景調用HI_MPI_ISP_GetLightboxGain()獲取Golden在差異標定環境下的
增益(avgRgain, avgBgain),在Cmos.c代碼通過宏定義的方式寫入Golden信息:
#define GOLDEN_RGAIN                          avgRgain
#define GOLDEN_BGAIN                          avgBgain

3、待標定的個體在D50, Flat環境,調用HI_MPI_ISP_GetLightboxGain()獲取sample的增益(avgRgain, avgBgain),
ISP_INIT_ATTR_S的u16SampleRgain=avgRgain;
ISP_INIT_ATTR_S的u16SampleBgain=avgBgain;
通過sensor_set_init()接口,配置到ISP內。
 
 
awb_cal  sample, 給客戶參考怎樣調用HI_MPI_ISP_GetLightboxGain接口。建議客戶根據實際應用修改下sample,
比如sample和golden的差異>門限時,可能這個樣片是異常的,篩出來,或者對這種情況做一個部分校正。
門限值和校正方案需要客戶根據個人要求來確定。
 
Shading標定原理跟離線標定原理一樣不做詳述。
 
 
 
做標定的時候,要製作一些59V200的標定板,跑這個標定sample,將每個sensor個體放在D50環境光源下,對着白牆或者白紙
分別進行shading和靜態AWB標定。標定得到的結果,自己通過軟件實現寫入到sensor存儲空間,業務運行時載入這些OTP數據

Linux+Liteos雙系統

1、shading標定使用方法:在liteos端輸入以下命令
    lsc_cal [vcapPipeHdl] [meshScale] [fileIndex]
    備註:標定數據存儲在 /app/sharefs目錄下,文件名爲:gain_[fileIndex].txt
    
2、awb標定使用方法:在liteos端輸入以下命令
    awb_cal [mode] [Rgain] [Bgain] [Alpha]
    備註:標定結果通過串口printf出來

修改前:before

\HiMobileCam\reference\actioncam\modules\init\amp\liteos\src\hi_product_init_main.c

/**
 * @file      hi_product_init_main.c
 * @brief     init in HuaweiLite
 *
 * Copyright (c) 2017 Huawei Tech.Co.,Ltd
 *
 * @author    HiMobileCam Reference Develop Team
 * @date      2018/3/20
 * @version   1.0

 */

#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* End of #ifdef __cplusplus */

#include "sys/types.h"
#include "sys/time.h"
#include "unistd.h"
#include "stdio.h"
#include "hi_type.h"
#include "asm/io.h"
#include "string.h"
#include "stdlib.h"
#include "pthread.h"
#include <sys/prctl.h>
#include "shell.h"
#include "hi_appcomm.h"

#include "hi_mapi_log.h"
#include "hi_product_init_os.h"
#include "hi_product_init_chip.h"
#include "hi_product_init_peripheral.h"
#include "hi_product_init_service.h"
#include "hi_timestamp.h"

static HI_S32 PDT_INIT_PreInit(HI_VOID)
{
    HI_S32 s32Ret = HI_SUCCESS;

    MLOGD("HI_PDT_INIT_OS_PreInit ...\n");
    s32Ret = HI_PDT_INIT_OS_PreInit();
    HI_APPCOMM_CHECK_RETURN(s32Ret, HI_FAILURE);

    MLOGD("HI_PDT_INIT_CHIP_PreInit ...\n");
    s32Ret = HI_PDT_INIT_CHIP_PreInit();
    HI_APPCOMM_CHECK_RETURN(s32Ret, HI_FAILURE);

    MLOGD("HI_PDT_INIT_PERIPHERAL_PreInit ...\n");
    s32Ret = HI_PDT_INIT_PERIPHERAL_PreInit();
    HI_APPCOMM_CHECK_RETURN(s32Ret, HI_FAILURE);
#ifndef CONFIG_PQT_STREAM_SUPPORT_ON
    MLOGD("HI_PDT_INIT_SERVICE_PreInit ...\n");
    s32Ret = HI_PDT_INIT_SERVICE_PreInit();
    HI_APPCOMM_CHECK_RETURN(s32Ret, HI_FAILURE);
#endif
    return s32Ret;
}

static HI_S32 PDT_INIT_Init(HI_VOID)
{
    HI_S32 s32Ret = HI_SUCCESS;

    MLOGD("HI_PDT_INIT_OS_Init ...\n");
    s32Ret = HI_PDT_INIT_OS_Init();
    HI_APPCOMM_CHECK_RETURN(s32Ret, HI_FAILURE);

    MLOGD("HI_PDT_INIT_CHIP_Init ...\n");
    s32Ret = HI_PDT_INIT_CHIP_Init();
    HI_APPCOMM_CHECK_RETURN(s32Ret, HI_FAILURE);

    MLOGD("HI_PDT_INIT_PERIPHERAL_Init ...\n");
    s32Ret = HI_PDT_INIT_PERIPHERAL_Init();
    HI_APPCOMM_CHECK_RETURN(s32Ret, HI_FAILURE);
#ifndef CONFIG_PQT_STREAM_SUPPORT_ON
    MLOGD("HI_PDT_INIT_SERVICE_Init ...\n");
    s32Ret = HI_PDT_INIT_SERVICE_Init();
    HI_APPCOMM_CHECK_RETURN(s32Ret, HI_FAILURE);
#endif
    return s32Ret;
}

static HI_S32 PDT_INIT_PostInit(HI_VOID)
{
    HI_S32 s32Ret = HI_SUCCESS;
    MLOGD("HI_PDT_INIT_OS_PostInit ...\n");
    HI_TIME_STAMP;
    s32Ret = HI_PDT_INIT_OS_PostInit();
    HI_APPCOMM_CHECK_RETURN(s32Ret, HI_FAILURE);

    MLOGD("HI_PDT_INIT_CHIP_PostInit ...\n");
    HI_TIME_STAMP;
    s32Ret = HI_PDT_INIT_CHIP_PostInit();
    HI_APPCOMM_CHECK_RETURN(s32Ret, HI_FAILURE);

    MLOGD("HI_PDT_INIT_PERIPHERAL_PostInit ...\n");
    HI_TIME_STAMP;
    s32Ret = HI_PDT_INIT_PERIPHERAL_PostInit();
    HI_APPCOMM_CHECK_RETURN(s32Ret, HI_FAILURE);
#ifndef CONFIG_PQT_STREAM_SUPPORT_ON
    MLOGD("HI_PDT_INIT_SERVICE_PostInit ...\n");
    HI_TIME_STAMP;
    s32Ret = HI_PDT_INIT_SERVICE_PostInit();
    HI_APPCOMM_CHECK_RETURN(s32Ret, HI_FAILURE);
#endif
    return s32Ret;
}

#ifdef CFG_DEBUG_LOG_ON

static HI_S32 PDT_INIT_SetLog(HI_S32 argc, HI_CHAR* argv[])
{
    if (3 != argc)
    {
        printf(
                "\n"
                "*************************************************\n"
                "Usage: ./setlog [LogOn] [LogTimeOn] [LogLevel]\n"
                "LogLevel: \n"
                "   HI_LOG_LEVEL_FATAL: %d\n"
                "   HI_LOG_LEVEL_ERROR: %d\n"
                "   HI_LOG_LEVEL_WARNING: %d\n"
                "   HI_LOG_LEVEL_INFO: %d\n"
                "   HI_LOG_LEVEL_DEBUG: %d\n"
                "e.g : ./setlog 1 1 3\n"
                "*************************************************\n"
                "\n", HI_LOG_LEVEL_FATAL, HI_LOG_LEVEL_ERROR, HI_LOG_LEVEL_WARNING,
                HI_LOG_LEVEL_INFO, HI_LOG_LEVEL_DEBUG);
        return HI_FAILURE;
    }
    HI_BOOL bLogOn = atoi(argv[0]);
    HI_BOOL bLogTimeOn = atoi(argv[1]);
    HI_LOG_LEVEL_E enLogLevel = atoi(argv[2]);
    HI_APPCOMM_CHECK_EXPR(((enLogLevel >= HI_LOG_LEVEL_FATAL) && (enLogLevel < HI_LOG_LEVEL_BUTT)) ,HI_FAILURE);
    MLOGD("LogOn[%d] LogTimeOn[%d] Level[%d]\n", bLogOn, bLogTimeOn, enLogLevel);
    HI_LOG_Config(bLogOn, bLogTimeOn, enLogLevel);
    return HI_SUCCESS;
}

#endif

static HI_VOID PDT_INIT_CmdReg(HI_VOID)
{
#ifdef CFG_DEBUG_LOG_ON
    osCmdReg(CMD_TYPE_EX, "setlog", 1, (CMD_CBK_FUNC)PDT_INIT_SetLog);
#endif
#ifdef CONFIG_PQT_SUPPORT_ON
    #ifdef CONFIG_PQT_STREAM_SUPPORT_ON
    extern HI_VOID app_stream(HI_S32 argc, HI_CHAR **argv );
    osCmdReg(CMD_TYPE_EX,"pq_stream", 0, (CMD_CBK_FUNC)app_stream);
    #endif
    extern HI_VOID app_control(HI_S32 argc, HI_CHAR **argv );
    osCmdReg(CMD_TYPE_EX,"pq_control", 0, (CMD_CBK_FUNC)app_control);
#endif
}

HI_VOID* PDT_INIT_Main(HI_VOID *arg)
{
    prctl(PR_SET_NAME, (unsigned long) "PDT_INIT_Main", 0, 0, 0);
#ifdef CONFIG_DEBUG
    HI_LOG_Config(HI_TRUE, HI_FALSE, HI_LOG_LEVEL_INFO);
    HI_MAPI_LOG_SetEnabledLevel(HI_MAPI_LOG_LEVEL_DEBUG);
#else
    HI_LOG_Config(HI_TRUE, HI_FALSE, HI_LOG_LEVEL_ERROR);
    HI_MAPI_LOG_SetEnabledLevel(HI_MAPI_LOG_LEVEL_ERR);
#endif
    HI_TIME_STAMP;
    PDT_INIT_PreInit();
    PDT_INIT_Init();
    PDT_INIT_PostInit();
    HI_TIME_STAMP;
    PDT_INIT_CmdReg();
    HI_TIME_PRINT;
    return HI_NULL;
}

static pthread_t s_AppInitThread = -1;
HI_VOID app_init(HI_VOID)
{
#ifdef TIME_STAMP_BASE_ADDR_LITEOS
    HI_TimeStamp_Init(TIME_STAMP_BASE_ADDR_LITEOS, HI_TRUE);
#endif

    HI_S32 s32Ret = HI_SUCCESS;
    pthread_attr_t attr;

    (HI_VOID)pthread_attr_setstacksize(&attr, 0xc000);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    attr.schedparam.sched_priority = 10;

    s32Ret = pthread_create(&s_AppInitThread, &attr, PDT_INIT_Main, HI_NULL);
    if (HI_SUCCESS != s32Ret)
    {
        MLOGE("pthread_create PDT_INIT_app fail\n");
    }
    pthread_attr_destroy(&attr);
    MLOGD("PDT_INIT_app successfull\n");
    return ;
}

#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* End of #ifdef __cplusplus */


修改後:after

\HiMobileCam\reference\actioncam\modules\init\amp\liteos\src\awb_calibration.c
\HiMobileCam\reference\actioncam\modules\init\amp\liteos\src\hi_product_init_main.c
\HiMobileCam\reference\actioncam\modules\init\amp\liteos\src\shading_calibration.c

新增了兩個文件,並且調用,程序開頭寫了文件名字

/**
 * @file      hi_product_init_main.c
 * @brief     init in HuaweiLite
 *
 * Copyright (c) 2017 Huawei Tech.Co.,Ltd
 *
 * @author    HiMobileCam Reference Develop Team
 * @date      2018/3/20
 * @version   1.0

 */

#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* End of #ifdef __cplusplus */

#include "sys/types.h"
#include "sys/time.h"
#include "unistd.h"
#include "stdio.h"
#include "hi_type.h"
#include "asm/io.h"
#include "string.h"
#include "stdlib.h"
#include "pthread.h"
#include <sys/prctl.h>
#include "shell.h"
#include "hi_appcomm.h"

#include "hi_mapi_log.h"
#include "hi_product_init_os.h"
#include "hi_product_init_chip.h"
#include "hi_product_init_peripheral.h"
#include "hi_product_init_service.h"
#include "hi_timestamp.h"

static HI_S32 PDT_INIT_PreInit(HI_VOID)
{
    HI_S32 s32Ret = HI_SUCCESS;

    MLOGD("HI_PDT_INIT_OS_PreInit ...\n");
    s32Ret = HI_PDT_INIT_OS_PreInit();
    HI_APPCOMM_CHECK_RETURN(s32Ret, HI_FAILURE);

    MLOGD("HI_PDT_INIT_CHIP_PreInit ...\n");
    s32Ret = HI_PDT_INIT_CHIP_PreInit();
    HI_APPCOMM_CHECK_RETURN(s32Ret, HI_FAILURE);

    MLOGD("HI_PDT_INIT_PERIPHERAL_PreInit ...\n");
    s32Ret = HI_PDT_INIT_PERIPHERAL_PreInit();
    HI_APPCOMM_CHECK_RETURN(s32Ret, HI_FAILURE);
#ifndef CONFIG_PQT_STREAM_SUPPORT_ON
    MLOGD("HI_PDT_INIT_SERVICE_PreInit ...\n");
    s32Ret = HI_PDT_INIT_SERVICE_PreInit();
    HI_APPCOMM_CHECK_RETURN(s32Ret, HI_FAILURE);
#endif
    return s32Ret;
}

static HI_S32 PDT_INIT_Init(HI_VOID)
{
    HI_S32 s32Ret = HI_SUCCESS;

    MLOGD("HI_PDT_INIT_OS_Init ...\n");
    s32Ret = HI_PDT_INIT_OS_Init();
    HI_APPCOMM_CHECK_RETURN(s32Ret, HI_FAILURE);

    MLOGD("HI_PDT_INIT_CHIP_Init ...\n");
    s32Ret = HI_PDT_INIT_CHIP_Init();
    HI_APPCOMM_CHECK_RETURN(s32Ret, HI_FAILURE);

    MLOGD("HI_PDT_INIT_PERIPHERAL_Init ...\n");
    s32Ret = HI_PDT_INIT_PERIPHERAL_Init();
    HI_APPCOMM_CHECK_RETURN(s32Ret, HI_FAILURE);
#ifndef CONFIG_PQT_STREAM_SUPPORT_ON
    MLOGD("HI_PDT_INIT_SERVICE_Init ...\n");
    s32Ret = HI_PDT_INIT_SERVICE_Init();
    HI_APPCOMM_CHECK_RETURN(s32Ret, HI_FAILURE);
#endif
    return s32Ret;
}

static HI_S32 PDT_INIT_PostInit(HI_VOID)
{
    HI_S32 s32Ret = HI_SUCCESS;
    MLOGD("HI_PDT_INIT_OS_PostInit ...\n");
    HI_TIME_STAMP;
    s32Ret = HI_PDT_INIT_OS_PostInit();
    HI_APPCOMM_CHECK_RETURN(s32Ret, HI_FAILURE);

    MLOGD("HI_PDT_INIT_CHIP_PostInit ...\n");
    HI_TIME_STAMP;
    s32Ret = HI_PDT_INIT_CHIP_PostInit();
    HI_APPCOMM_CHECK_RETURN(s32Ret, HI_FAILURE);

    MLOGD("HI_PDT_INIT_PERIPHERAL_PostInit ...\n");
    HI_TIME_STAMP;
    s32Ret = HI_PDT_INIT_PERIPHERAL_PostInit();
    HI_APPCOMM_CHECK_RETURN(s32Ret, HI_FAILURE);
#ifndef CONFIG_PQT_STREAM_SUPPORT_ON
    MLOGD("HI_PDT_INIT_SERVICE_PostInit ...\n");
    HI_TIME_STAMP;
    s32Ret = HI_PDT_INIT_SERVICE_PostInit();
    HI_APPCOMM_CHECK_RETURN(s32Ret, HI_FAILURE);
#endif
    return s32Ret;
}

#ifdef CFG_DEBUG_LOG_ON

static HI_S32 PDT_INIT_SetLog(HI_S32 argc, HI_CHAR* argv[])
{
    if (3 != argc)
    {
        printf(
                "\n"
                "*************************************************\n"
                "Usage: ./setlog [LogOn] [LogTimeOn] [LogLevel]\n"
                "LogLevel: \n"
                "   HI_LOG_LEVEL_FATAL: %d\n"
                "   HI_LOG_LEVEL_ERROR: %d\n"
                "   HI_LOG_LEVEL_WARNING: %d\n"
                "   HI_LOG_LEVEL_INFO: %d\n"
                "   HI_LOG_LEVEL_DEBUG: %d\n"
                "e.g : ./setlog 1 1 3\n"
                "*************************************************\n"
                "\n", HI_LOG_LEVEL_FATAL, HI_LOG_LEVEL_ERROR, HI_LOG_LEVEL_WARNING,
                HI_LOG_LEVEL_INFO, HI_LOG_LEVEL_DEBUG);
        return HI_FAILURE;
    }
    HI_BOOL bLogOn = atoi(argv[0]);
    HI_BOOL bLogTimeOn = atoi(argv[1]);
    HI_LOG_LEVEL_E enLogLevel = atoi(argv[2]);
    HI_APPCOMM_CHECK_EXPR(((enLogLevel >= HI_LOG_LEVEL_FATAL) && (enLogLevel < HI_LOG_LEVEL_BUTT)) ,HI_FAILURE);
    MLOGD("LogOn[%d] LogTimeOn[%d] Level[%d]\n", bLogOn, bLogTimeOn, enLogLevel);
    HI_LOG_Config(bLogOn, bLogTimeOn, enLogLevel);
    return HI_SUCCESS;
}

#endif

static HI_VOID PDT_INIT_CmdReg(HI_VOID)
{
#ifdef CFG_DEBUG_LOG_ON
    osCmdReg(CMD_TYPE_EX, "setlog", 1, (CMD_CBK_FUNC)PDT_INIT_SetLog);
#endif
#ifdef CONFIG_PQT_SUPPORT_ON
    #ifdef CONFIG_PQT_STREAM_SUPPORT_ON
    extern HI_VOID app_stream(HI_S32 argc, HI_CHAR **argv );
    osCmdReg(CMD_TYPE_EX,"pq_stream", 0, (CMD_CBK_FUNC)app_stream);
    #endif
    extern HI_VOID app_control(HI_S32 argc, HI_CHAR **argv );
    osCmdReg(CMD_TYPE_EX,"pq_control", 0, (CMD_CBK_FUNC)app_control);
#endif

    extern HI_VOID lsc_cal(HI_S32 argc, HI_CHAR **argv );
    osCmdReg(CMD_TYPE_EX,"lsc_cal", 0, (CMD_CBK_FUNC)lsc_cal);

    extern HI_VOID awb_cal(HI_S32 argc, HI_CHAR **argv );
    osCmdReg(CMD_TYPE_EX,"awb_cal", 0, (CMD_CBK_FUNC)awb_cal);
}

HI_VOID* PDT_INIT_Main(HI_VOID *arg)
{
    prctl(PR_SET_NAME, (unsigned long) "PDT_INIT_Main", 0, 0, 0);
#ifdef CONFIG_DEBUG
    HI_LOG_Config(HI_TRUE, HI_FALSE, HI_LOG_LEVEL_INFO);
    HI_MAPI_LOG_SetEnabledLevel(HI_MAPI_LOG_LEVEL_DEBUG);
#else
    HI_LOG_Config(HI_TRUE, HI_FALSE, HI_LOG_LEVEL_ERROR);
    HI_MAPI_LOG_SetEnabledLevel(HI_MAPI_LOG_LEVEL_ERR);
#endif
    HI_TIME_STAMP;
    PDT_INIT_PreInit();
    PDT_INIT_Init();
    PDT_INIT_PostInit();
    HI_TIME_STAMP;
    PDT_INIT_CmdReg();
    HI_TIME_PRINT;
    return HI_NULL;
}

static pthread_t s_AppInitThread = -1;
HI_VOID app_init(HI_VOID)
{
#ifdef TIME_STAMP_BASE_ADDR_LITEOS
    HI_TimeStamp_Init(TIME_STAMP_BASE_ADDR_LITEOS, HI_TRUE);
#endif

    HI_S32 s32Ret = HI_SUCCESS;
    pthread_attr_t attr;

    (HI_VOID)pthread_attr_setstacksize(&attr, 0xc000);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    attr.schedparam.sched_priority = 10;

    s32Ret = pthread_create(&s_AppInitThread, &attr, PDT_INIT_Main, HI_NULL);
    if (HI_SUCCESS != s32Ret)
    {
        MLOGE("pthread_create PDT_INIT_app fail\n");
    }
    pthread_attr_destroy(&attr);
    MLOGD("PDT_INIT_app successfull\n");
    return ;
}

#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* End of #ifdef __cplusplus */


/******************************************************************************

  Copyright (C), 2016-2016, Hisilicon Tech. Co., Ltd.

 ******************************************************************************
  File Name     : Sample_awb_correction.c
  Version       : Initial Draft
  Author        : Hisilicon BVT PQ group
  Created       : 2016/12/15
  Description   :
  History       :
  1.Date        : 2016/12/15
    Author      : h00372898
    Modification: Created file

******************************************************************************/

#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* End of #ifdef __cplusplus */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/time.h>
#include <math.h>


#include "mpi_isp.h"
#include "hi_comm_isp.h"
#include "mpi_ae.h"

#include "hi_appcomm_log.h"

void SAMPLE_AWB_CORRECTION_Usage(HI_VOID)
{
    printf("\n");
    printf("Usage: [mode] [intf1] [intf2] [intf3]\n");

    printf("mode:\n");
    printf("\t 0) Calculate Sample gain.\n");
    printf("\t 1) Adjust Sample gain according to Golden Sample.\n");

    printf("intf1:\n");
    printf("\t The value of Rgain of Golden Sample.\n");

    printf("intf2:\n");
    printf("\t The value of Bgain of Golden Sample.\n");

    printf("intf3:\n");
    printf("\t The value of Alpha ranging from 0 to 1024 (The strength of adusting Sampe Gain will increase with the value of Alpha) .\n");
    printf("\n");
    return;
}

int awb_cal(int argc, char *argv[])
{
    if (argc != 4) {
        SAMPLE_AWB_CORRECTION_Usage();
        return HI_SUCCESS;
    }

    HI_S16 total_count = 0;
    HI_S16 stable_count = 0;
    VI_PIPE ViPipe = 0;
    HI_U16 u16GoldenRgain = 0;
    HI_U16 u16GoldenBgain = 0;
    HI_S16 s16Alpha = 0;
    HI_U32 u32Mode = 0;

    ISP_EXP_INFO_S stExpInfo;
    ISP_EXPOSURE_ATTR_S stExpAttr;

#ifndef __HuaweiLite__
    if ( (argc < 2) || (1 != strlen(argv[1])))
    {
        SAMPLE_AWB_CORRECTION_Usage(argv[0]);
        return HI_FAILURE;
    }
    if ( (argc < 5) && ('1' == *argv[1]))
    {
        SAMPLE_AWB_CORRECTION_Usage(argv[0]);
        return HI_FAILURE;
    }
#endif
    HI_MPI_ISP_GetExposureAttr(ViPipe, &stExpAttr);

    printf("set antiflicker enable and the value of frequency to 50Hz\n");
    stExpAttr.stAuto.stAntiflicker.bEnable = HI_TRUE;
    stExpAttr.stAuto.stAntiflicker.u8Frequency = 50;
    HI_MPI_ISP_SetExposureAttr(ViPipe, &stExpAttr);

    switch (*argv[0])
    {
        case '0':
            u32Mode = 0;
            u16GoldenRgain = 0;
            u16GoldenBgain = 0;
            break;

        case '1':
            u32Mode = 1;
            u16GoldenRgain = atoi(argv[1]);
            u16GoldenBgain = atoi(argv[2]);
            s16Alpha = atoi(argv[3]);
            break;

        default:
            MLOGE("the mode[%u] is invaild!\n", atoi(argv[0]));
            SAMPLE_AWB_CORRECTION_Usage();
            return HI_SUCCESS;
    }

    do
    {
        HI_MPI_ISP_QueryExposureInfo(ViPipe, &stExpInfo);
        usleep(100000000 / DIV_0_TO_1(stExpInfo.u32Fps));

        /*judge whether AE is stable*/
        if (stExpInfo.s16HistError > stExpAttr.stAuto.u8Tolerance)
        {
            stable_count = 0;
        }
        else
        {
            stable_count ++;
        }
        total_count ++;
    }
    while ((stable_count < 5) && (total_count < 20));


    if (stable_count >= 5)
    {
        ISP_AWB_Calibration_Gain_S stAWBCalibGain;
        HI_MPI_ISP_GetLightboxGain(ViPipe, &stAWBCalibGain);
        /*Adjust the value of Rgain and Bgain of Sample according to Golden Sample*/
        if (1 == u32Mode)
        {
            stAWBCalibGain.u16AvgRgain =  (HI_U16)((HI_S16)(stAWBCalibGain.u16AvgRgain)  + ((((HI_S16)u16GoldenRgain - (HI_S16)(stAWBCalibGain.u16AvgRgain))* s16Alpha) >> 10));
            stAWBCalibGain.u16AvgBgain = (HI_U16)((HI_S16)(stAWBCalibGain.u16AvgBgain) + ((((HI_S16)u16GoldenBgain  - (HI_S16)(stAWBCalibGain.u16AvgBgain))* s16Alpha) >> 10 ));
        }

#if 1
    if (0 == u32Mode)
    {
        printf("Calculate Sample gain:\n");
    }
    else if (1 == u32Mode)
    {
        printf("Adjust Sample gain:\n");
    }
    MLOGI(GREEN"avgRgain = %u, avgBgain = %u\n"NONE, stAWBCalibGain.u16AvgRgain, stAWBCalibGain.u16AvgBgain);
#endif
        return HI_SUCCESS;
    }
    else
    {
        printf("AE IS NOT STABLE,PLEASE WAIT");
        return HI_FAILURE;
    }

}

#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#ifndef __HuaweiLite__
#include <sys/poll.h>
#endif
#include <sys/time.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <sys/prctl.h>

#include "hi_common.h"
#include "hi_comm_video.h"
#include "hi_comm_sys.h"
#include "hi_comm_vi.h"
#include "hi_comm_isp.h"
#include "mpi_vb.h"
#include "mpi_sys.h"
#include "mpi_vi.h"
#include "mpi_isp.h"


#define DUMP_RAW 0
#define SAVE_LSC 1

#define MAX_FRM_CNT     25
#define MAX_FRM_WIDTH   8192

#define ALIGN_BACK(x, a)              ((a) * (((x) / (a))))

typedef struct {
    HI_HANDLE vcapPipeHdl;
    HI_U32 meshScale;
    HI_U32 fileIndex;
} LSC_CAL_PARAM;

#if 1
#define MEM_DEV_OPEN() \
    do {\
        if (s_s32MemDev <= 0)\
        {\
            s_s32MemDev = open("/dev/mem", O_CREAT|O_RDWR|O_SYNC);\
            if (s_s32MemDev < 0)\
            {\
                perror("Open dev/mem error");\
                return -1;\
            }\
        }\
    }while(0)

#define MEM_DEV_CLOSE() \
    do {\
        HI_S32 s32Ret;\
        if (s_s32MemDev > 0)\
        {\
            s32Ret = close(s_s32MemDev);\
            if(HI_SUCCESS != s32Ret)\
            {\
                perror("Close mem/dev Fail");\
                return s32Ret;\
            }\
            s_s32MemDev = -1;\
        }\
    }while(0)
#endif

static pthread_t g_lscCalThread;

/******************************************************************************
* function : to process abnormal case
******************************************************************************/
void SAMPLE_LSCCALI_HandleSig(HI_S32 signo)
{
    if (SIGINT == signo || SIGTERM == signo)
    {
        SAMPLE_COMM_All_ISP_Stop();
        SAMPLE_COMM_SYS_Exit();
        printf("\033[0;31mprogram termination abnormally!\033[0;39m\n");
    }
    exit(-1);
}

HI_S32 get_raw_pts(VIDEO_FRAME_INFO_S** pastFrame, HI_U64 u64RawPts, HI_U32 u32RowCnt,
                   HI_U32 u32ColCnt, HI_U32 u32Col,  HI_U32* pu32Index)
{
    HI_S32 i;

    for (i = 0; i < u32RowCnt; i++)
    {
        printf("get_raw_pts  --pts is %lld.\n", pastFrame[i][u32Col].stVFrame.u64PTS);

        if (u64RawPts == pastFrame[i][u32Col].stVFrame.u64PTS)
        {
            *pu32Index = i;
            return 0;
        }
    }

    return -1;
}

HI_S32 getDumpPipe(VI_DEV ViDev, WDR_MODE_E enInWDRMode, HI_U32 *pu32PipeNum, VI_PIPE ViPipeId[])
{
    HI_S32 s32Ret;
    HI_U32 u32PipeNum, i;
    VI_DEV_BIND_PIPE_S stDevBindPipe;

    memset(&stDevBindPipe, 0, sizeof(stDevBindPipe));
    s32Ret = HI_MPI_VI_GetDevBindPipe(ViDev, &stDevBindPipe);
    if (HI_SUCCESS != s32Ret)
    {
        printf("HI_MPI_VI_GetDevBindPipe error 0x%x !\n", s32Ret);
        return s32Ret;
    }

    u32PipeNum = 0;

    switch (enInWDRMode)
    {
        case WDR_MODE_NONE:
        case WDR_MODE_BUILT_IN:
            if (stDevBindPipe.u32Num < 1)
            {
                printf("PipeNum(%d) enInWDRMode(%d) don't match !\n", stDevBindPipe.u32Num, enInWDRMode);
                return HI_FAILURE;
            }
            u32PipeNum = 1;
            ViPipeId[0] = stDevBindPipe.PipeId[0];
            ViPipeId[4] = stDevBindPipe.PipeId[0];
            break;

        case WDR_MODE_2To1_LINE:
        case WDR_MODE_2To1_FRAME:
        case WDR_MODE_2To1_FRAME_FULL_RATE:
            if (2 != stDevBindPipe.u32Num)
            {
                printf("PipeNum(%d) enInWDRMode(%d) don't match !\n", stDevBindPipe.u32Num, enInWDRMode);
                return HI_FAILURE;
            }
            u32PipeNum = 2;
            for (i = 0; i < u32PipeNum; i++)
            {
                ViPipeId[i] = stDevBindPipe.PipeId[i];
            }
            ViPipeId[4] = stDevBindPipe.PipeId[0];
            break;

        case WDR_MODE_3To1_LINE:
        case WDR_MODE_3To1_FRAME:
        case WDR_MODE_3To1_FRAME_FULL_RATE:
            if (3 != stDevBindPipe.u32Num)
            {
                printf("PipeNum(%d) enInWDRMode(%d) don't match !\n", stDevBindPipe.u32Num, enInWDRMode);
                return HI_FAILURE;
            }
            u32PipeNum = 3;
            for (i = 0; i < u32PipeNum; i++)
            {
                ViPipeId[i] = stDevBindPipe.PipeId[i];
            }
            ViPipeId[4] = stDevBindPipe.PipeId[0];
            break;

        case WDR_MODE_4To1_LINE:
        case WDR_MODE_4To1_FRAME:
        case WDR_MODE_4To1_FRAME_FULL_RATE:
            if (4 != stDevBindPipe.u32Num)
            {
                printf("PipeNum(%d) enInWDRMode(%d) don't match !\n", stDevBindPipe.u32Num, enInWDRMode);
                return HI_FAILURE;
            }
            u32PipeNum = 4;
            for (i = 0; i < u32PipeNum; i++)
            {
                ViPipeId[i] = stDevBindPipe.PipeId[i];
            }
            ViPipeId[4] = stDevBindPipe.PipeId[0];
            break;

        default:
            printf("enInWDRMode(%d) error !\n", enInWDRMode);
            return HI_FAILURE;
    }

    *pu32PipeNum = u32PipeNum;

    return HI_SUCCESS;
}


static inline HI_S32 bitWidth2PixelFormat(HI_U32 u32Nbit, PIXEL_FORMAT_E *penPixelFormat)
{
    PIXEL_FORMAT_E enPixelFormat;

    if (8 == u32Nbit)
    {
        enPixelFormat = PIXEL_FORMAT_RGB_BAYER_8BPP;
    }
    else if (10 == u32Nbit)
    {
        enPixelFormat = PIXEL_FORMAT_RGB_BAYER_10BPP;
    }
    else if (12 == u32Nbit)
    {
        enPixelFormat = PIXEL_FORMAT_RGB_BAYER_12BPP;
    }
    else if (14 == u32Nbit)
    {
        enPixelFormat = PIXEL_FORMAT_RGB_BAYER_14BPP;
    }
    else if (16 == u32Nbit)
    {
        enPixelFormat = PIXEL_FORMAT_RGB_BAYER_16BPP;
    }
    else
    {
        enPixelFormat = PIXEL_FORMAT_RGB_BAYER_16BPP;
    }

    *penPixelFormat = enPixelFormat;
    return HI_SUCCESS;
}

static HI_S32 pixelFormat2BitWidth(PIXEL_FORMAT_E *penPixelFormat)
{
    PIXEL_FORMAT_E enPixelFormat;
    enPixelFormat = *penPixelFormat;
    HI_S32 s32BitWidth;
    switch(enPixelFormat)
    {
    case PIXEL_FORMAT_RGB_BAYER_8BPP:
        {
            s32BitWidth = 8;
        }
        break;
    case PIXEL_FORMAT_RGB_BAYER_10BPP:
        {
            s32BitWidth = 10;
        }
        break;
    case PIXEL_FORMAT_RGB_BAYER_12BPP:
        {
            s32BitWidth = 12;
        }
        break;
    case PIXEL_FORMAT_RGB_BAYER_14BPP:
        {
            s32BitWidth = 14;
        }
        break;
    case PIXEL_FORMAT_RGB_BAYER_16BPP:
        {
            s32BitWidth = 16;
        }
        break;
    default:
        s32BitWidth = HI_FAILURE;
        break;
    }

    return s32BitWidth;
}

HI_S32 convertBitPixel(HI_U8 *pu8Data, HI_U32 u32DataNum, HI_U32 u32BitWidth, HI_U16 *pu16OutData)
{
    HI_S32 i, u32Tmp, s32OutCnt;
    HI_U32 u32Val;
    HI_U64 u64Val;
    HI_U8 *pu8Tmp = pu8Data;

    s32OutCnt = 0;
    switch(u32BitWidth)
    {
    case 10:
        {
            /* 4 pixels consist of 5 bytes  */
            u32Tmp = u32DataNum / 4;

            for (i = 0; i < u32Tmp; i++)
            {
                /* byte4 byte3 byte2 byte1 byte0 */
                pu8Tmp = pu8Data + 5 * i;
                u64Val = pu8Tmp[0] + ((HI_U32)pu8Tmp[1] << 8) + ((HI_U32)pu8Tmp[2] << 16) +
                         ((HI_U32)pu8Tmp[3] << 24) + ((HI_U64)pu8Tmp[4] << 32);

                pu16OutData[s32OutCnt++] = u64Val & 0x3ff;
                pu16OutData[s32OutCnt++] = (u64Val >> 10) & 0x3ff;
                pu16OutData[s32OutCnt++] = (u64Val >> 20) & 0x3ff;
                pu16OutData[s32OutCnt++] = (u64Val >> 30) & 0x3ff;
            }
        }
        break;
    case 12:
        {
            /* 2 pixels consist of 3 bytes  */
            u32Tmp = u32DataNum / 2;

            for (i = 0; i < u32Tmp; i++)
            {
                /* byte2 byte1 byte0 */
                pu8Tmp = pu8Data + 3 * i;
                u32Val = pu8Tmp[0] + (pu8Tmp[1] << 8) + (pu8Tmp[2] << 16);
                pu16OutData[s32OutCnt++] = u32Val & 0xfff;
                pu16OutData[s32OutCnt++] = (u32Val >> 12) & 0xfff;
            }
        }
        break;
    case 14:
        {
            /* 4 pixels consist of 7 bytes  */
            u32Tmp = u32DataNum / 4;

            for (i = 0; i < u32Tmp; i++)
            {
                pu8Tmp = pu8Data + 7 * i;
                u64Val = pu8Tmp[0] + ((HI_U32)pu8Tmp[1] << 8) + ((HI_U32)pu8Tmp[2] << 16) +
                         ((HI_U32)pu8Tmp[3] << 24) + ((HI_U64)pu8Tmp[4] << 32) +
                         ((HI_U64)pu8Tmp[5] << 40) + ((HI_U64)pu8Tmp[6] << 48);

                pu16OutData[s32OutCnt++] = u64Val & 0x3fff;
                pu16OutData[s32OutCnt++] = (u64Val >> 14) & 0x3fff;
                pu16OutData[s32OutCnt++] = (u64Val >> 28) & 0x3fff;
                pu16OutData[s32OutCnt++] = (u64Val >> 42) & 0x3fff;
            }
        }
        break;
    case 16:
        {
            /* 1 pixels consist of 2 bytes */
            u32Tmp = u32DataNum;

            for (i = 0; i < u32Tmp; i++)
            {
                /* byte1 byte0 */
                pu8Tmp = pu8Data + 2 * i;
                u32Val = pu8Tmp[0] + (pu8Tmp[1] << 8);
                pu16OutData[s32OutCnt++] = u32Val & 0xffff;
            }
        }
        break;
    default:
        fprintf(stderr, "unsupport bitWidth: %d\n", u32BitWidth);
        return HI_FAILURE;
        break;
    }

    return s32OutCnt;
}

HI_S32 mesh_calibration_proc(VI_PIPE ViPipe,VIDEO_FRAME_S* pVBuf, HI_U32 u32MeshScale, HI_U32 u32ByteAlign, ISP_MESH_SHADING_TABLE_S *pstMLSCTable)
{

    //HI_U32 u32H;
    HI_U16 *pu16Data = NULL;
    HI_U64 phy_addr, size;
    HI_U8* pUserPageAddr[2];
    HI_U8  *pu8Data;
    HI_U32 u32Nbit = 0;

    HI_S32 s32Ret;
    PIXEL_FORMAT_E enPixelFormat = pVBuf->enPixelFormat;

    ISP_MLSC_CALIBRATION_CFG_S  stMLSCCaliCfg;
    ISP_PUB_ATTR_S    stIspPubAttr;
    ISP_BLACK_LEVEL_S stBlackLevel;

    u32Nbit = pixelFormat2BitWidth(&enPixelFormat);

    size = (pVBuf->u32Stride[0]) * (pVBuf->u32Height);
    phy_addr = pVBuf->u64PhyAddr[0];

    pUserPageAddr[0] = (HI_U8*) HI_MPI_SYS_Mmap(phy_addr, size);
    if (NULL == pUserPageAddr[0])
    {
        return HI_FAILURE;
    }

    if (10 != u32Nbit &&  12 != u32Nbit &&  14 != u32Nbit &&  16 != u32Nbit)
    {
        printf("can't not support %d bits raw, only support 10bits,12bits,14bits,16bits\n", u32Nbit);
        exit(HI_FAILURE);
    }

HI_U32 u32H;
#if  DUMP_RAW
    FILE* pfd;

    printf("Dump raw frame of vi  to file: \n");

    /* open file */
    pfd = fopen("/app/sharefs/lsc.raw", "wb");
    if (NULL == pfd)
    {
        printf("open file failed:%s!\n", strerror(errno));
        return HI_FAILURE;
    }

    pu8Data = pUserPageAddr[0];
    if (8 != u32Nbit)
    {
        pu16Data = (HI_U16*)malloc(pVBuf->u32Width * 2);
        if (NULL == pu16Data)
        {
            fprintf(stderr, "alloc memory failed\n");
            HI_MPI_SYS_Munmap(pUserPageAddr[0], size);
            pUserPageAddr[0] = NULL;
            return HI_FAILURE;
        }
    }

    /* save Y ----------------------------------------------------------------*/
    fprintf(stderr, "saving......dump data......u32Stride[0]: %d, width: %d\n", pVBuf->u32Stride[0], pVBuf->u32Width);
    //fprintf(stderr, "pts: %lld\n", pVBuf->stSupplement.u64RawPts);
    fflush(stderr);

    for (u32H = 0; u32H < pVBuf->u32Height; u32H++)
    {
        if (8 == u32Nbit)
        {
            fwrite(pu8Data, pVBuf->u32Width, 1, pfd);
        }
        else if (16 == u32Nbit)
        {
            fwrite(pu8Data, pVBuf->u32Width, 2, pfd);
            fflush(pfd);
        }
        else
        {
            convertBitPixel(pu8Data, pVBuf->u32Width, u32Nbit, pu16Data);
            fwrite(pu16Data, pVBuf->u32Width, 2, pfd);
        }
        pu8Data += pVBuf->u32Stride[0];
    }
    fflush(pfd);

    fprintf(stderr, "done u32TimeRef: %d!\n", pVBuf->u32TimeRef);
    //fprintf(stderr, "vc num: %lld!\n", pVBuf->u64PrivateData);
    fflush(stderr);
    fclose(pfd);
#endif

    if (NULL != pu16Data)
    {
        free(pu16Data);
    }

    pu8Data = pUserPageAddr[0];
    pu16Data = (HI_U16*)malloc(sizeof(HI_U16)*pVBuf->u32Width * pVBuf->u32Height);
    if (NULL == pu16Data)
    {
        fprintf(stderr, "alloc memory failed\n");
        HI_MPI_SYS_Munmap(pUserPageAddr[0], size);
        pUserPageAddr[0] = NULL;
        return HI_FAILURE;
    }

    for (u32H = 0; u32H < pVBuf->u32Height; u32H++)
    {
        convertBitPixel(pu8Data, pVBuf->u32Width, u32Nbit, pu16Data);
        pu8Data += pVBuf->u32Stride[0];
        pu16Data += pVBuf->u32Width;
    }
    pu16Data -= pVBuf->u32Width * pVBuf->u32Height;

    /*Calibration parameter preset*/
    stMLSCCaliCfg.enRawBit = u32Nbit;
    stMLSCCaliCfg.u32MeshScale = u32MeshScale;

    HI_MPI_ISP_GetPubAttr(ViPipe, &stIspPubAttr);
    stMLSCCaliCfg.enBayer  = stIspPubAttr.enBayer;
    stMLSCCaliCfg.u16ImgWidth = pVBuf->u32Width;
    stMLSCCaliCfg.u16ImgHeight = pVBuf->u32Height;

    //Default setting without crop, if need to crop, please set the right crop parameters.
    stMLSCCaliCfg.u16DstImgWidth = stMLSCCaliCfg.u16ImgWidth;
    stMLSCCaliCfg.u16DstImgHeight = stMLSCCaliCfg.u16ImgHeight;
    stMLSCCaliCfg.u16OffsetX = 0;
    stMLSCCaliCfg.u16OffsetY = 0;

    HI_MPI_ISP_GetBlackLevelAttr(ViPipe, &stBlackLevel);
    stMLSCCaliCfg.u16BLCOffsetR  = stBlackLevel.au16BlackLevel[0];
    stMLSCCaliCfg.u16BLCOffsetGr = stBlackLevel.au16BlackLevel[1];
    stMLSCCaliCfg.u16BLCOffsetGb = stBlackLevel.au16BlackLevel[2];
    stMLSCCaliCfg.u16BLCOffsetB  = stBlackLevel.au16BlackLevel[3];

    //printf("BLC level is %d \n", stMLSCCaliCfg.u16BLCOffsetR);
    s32Ret = HI_MPI_ISP_MeshShadingCalibration(ViPipe, pu16Data, &stMLSCCaliCfg, pstMLSCTable);
    if(HI_SUCCESS != s32Ret)
    {
        if (NULL != pu16Data)
        {
            free(pu16Data);
        }
        HI_MPI_SYS_Munmap(pUserPageAddr[0], size);
        pUserPageAddr[0] = NULL;

        return HI_FAILURE;
    }

    if (NULL != pu16Data)
    {
        free(pu16Data);
    }

    HI_MPI_SYS_Munmap(pUserPageAddr[0], size);
    pUserPageAddr[0] = NULL;
    fprintf(stderr, "------Done!\n");

    return HI_SUCCESS;

}



HI_S32 lsc_online_cali_proc(VI_PIPE ViPipe, HI_U32 u32MeshScale, HI_U32 fileIndex,
    HI_U32 u32Cnt, HI_U32 u32ByteAlign, HI_U32 u32RatioShow)
{
    int                    i, j;
//  int                    ret;
    //HI_CHAR                szYuvName[300] = {0};
    //FILE*                  pfd = NULL;
    HI_S32                 s32MilliSec = 4000;
    HI_U32                 u32CapCnt = 0;
    //HI_U64                 u64IspInfoPhyAddr = 0;
    //VI_CMP_PARAM_S         stCmpPara;
    //ISP_FRAME_INFO_S*      pstIspFrameInfo;
    //ISP_PUB_ATTR_S         stPubAttr;
//  VIDEO_FRAME_INFO_S     stFrame;
    VIDEO_FRAME_INFO_S     astFrame[MAX_FRM_CNT];
    ISP_MESH_SHADING_TABLE_S  stIspMLSCTable;

    /* get VI frame  */
    for (i = 0; i < u32Cnt; i++)
    {
        if (HI_SUCCESS != HI_MPI_VI_GetPipeFrame(ViPipe, &astFrame[i], s32MilliSec))
        {
            printf("get vi Pipe %d frame err\n", ViPipe);
            printf("only get %d frame\n", i);
            break;
        }

        printf("get vi Pipe %d frame num %d ok\n",ViPipe,  i);
    }

    u32CapCnt = i;

    if (0 == u32CapCnt)
    {
        return HI_FAILURE;
    }

    //testIspDngInfo(ViPipe, &stFrame);

    //HI_MPI_VI_ReleasePipeFrame(ViPipe, &stFrame);

    /* dump file */


    for (j = 0; j < u32CapCnt; j++)
    {
        /* save VI frame to file */
        mesh_calibration_proc(ViPipe, &astFrame[j].stVFrame, u32MeshScale, u32ByteAlign, &stIspMLSCTable);

        /* release frame after using */
        HI_MPI_VI_ReleasePipeFrame(ViPipe, &astFrame[j]);
    }

#if SAVE_LSC
    HI_CHAR filePath[128] = {};
    snprintf(filePath, sizeof(filePath), "%s_%u.txt", "/app/sharefs/gain", fileIndex);
    FILE *pFile = fopen(filePath, "wb");
    if(!pFile)
    {
        printf("create file fails\n");
        return -1;
    }
    fprintf(pFile,"stIspShardingTable.au32XGridWidth = ");
    for(i= 0;i < 16;i++)
    {
        fprintf(pFile,"%d,",stIspMLSCTable.au16XGridWidth[i]);
    }
    fprintf(pFile,"\n");
    fprintf(pFile,"stIspShardingTable.au32YGridHeight = ");
    for(i= 0;i < 16;i++)
    {
        fprintf(pFile,"%d,",stIspMLSCTable.au16YGridWidth[i]);
    }
    fprintf(pFile,"\n");
    fprintf(pFile,"R = \n");
    for(i=0;i<33;i++)
    {
        for(j = 0;j<33;j++)
        {
            fprintf(pFile,"%d,",stIspMLSCTable.stLscGainLut.au16RGain[i*33+j]);
        }
        fprintf(pFile,"\n");
    }
    fprintf(pFile,"Gr\n");
    for(i=0;i<33;i++)
    {
        for(j = 0;j<33;j++)
        {
            fprintf(pFile,"%d,",stIspMLSCTable.stLscGainLut.au16GrGain[i*33+j]);
        }
        fprintf(pFile,"\n");
    }
    fprintf(pFile,"Gb\n");
    for(i=0;i<33;i++)
    {
        for(j = 0;j<33;j++)
        {
            fprintf(pFile,"%d,",stIspMLSCTable.stLscGainLut.au16GbGain[i*33+j]);
        }
        fprintf(pFile,"\n");
    }
    fprintf(pFile,"B\n");
    for(i=0;i<33;i++)
    {
        for(j = 0;j<33;j++)
        {
            fprintf(pFile,"%d,",stIspMLSCTable.stLscGainLut.au16BGain[i*33+j]);
        }
        fprintf(pFile,"\n");
    }
    fclose(pFile);

#endif

    return HI_SUCCESS;
}

static HI_S32 lsc_run(HI_HANDLE vcapPipeHdl, HI_U32 meshScale, HI_U32 fileIndex)
{
    VI_DEV            ViDev                = 0;
    VI_PIPE           ViPipeId[4]          = {0};  /* save main pipe to [4] */
    HI_S32            s32Ret               = 0;
    HI_U32            i                    = 0;
    HI_U32            u32FrmCnt            = 1;
    HI_U32            u32RawDepth          = 2;
    HI_U32            u32ByteAlign         = 1;
    HI_U32            u32PipeNum           = 0;   /* LineMode -> 1, WDRMode -> 2~3 */
    HI_U32            u32RatioShow         = 1;
    COMPRESS_MODE_E   enCompressMode       = COMPRESS_MODE_NONE;
    VI_DUMP_ATTR_S    stRawDumpAttr;
    VI_DUMP_ATTR_S    stDumpAttr;
    VI_DEV_ATTR_S     stDevAttr;
    VI_PIPE_ATTR_S    astBackUpPipeAttr[4];
    VI_PIPE_ATTR_S    stPipeAttr;

    //enCompressMode = COMPRESS_MODE_NONE; /* non_compress_mode */
    u32FrmCnt      = 1;  /* frame number is 1 */
    u32ByteAlign   = 1;  /* convert to Byte align */
    u32RatioShow   = 0;  /* ratio not shown */

    if (1 > u32FrmCnt || MAX_FRM_CNT < u32FrmCnt)
    {
        printf("invalid FrmCnt %d, FrmCnt range from 1 to %d\n", u32FrmCnt, MAX_FRM_CNT);
        exit(HI_FAILURE);
    }

    s32Ret = HI_MPI_VI_GetDevAttr(ViDev, &stDevAttr);

    if (HI_SUCCESS != s32Ret)
    {
        printf("Get dev %d attr failed!\n", ViDev);
        return s32Ret;
    }

    s32Ret = getDumpPipe(ViDev, stDevAttr.stWDRAttr.enWDRMode, &u32PipeNum, ViPipeId);

    if (HI_SUCCESS != s32Ret)
    {
        printf("getDumpPipe failed 0x%x!\n", s32Ret);
        return HI_ERR_VI_INVALID_PARA;
    }

    printf("Setting Parameter ==> MeshScale =%d\n", meshScale);

    for (i = 0; i < u32PipeNum; i++)
    {
        s32Ret = HI_MPI_VI_GetPipeDumpAttr(ViPipeId[i], &stRawDumpAttr);

        if (HI_SUCCESS != s32Ret)
        {
            printf("Get Pipe %d dump attr failed!\n", vcapPipeHdl);
            return s32Ret;
        }

        memcpy(&stDumpAttr, &stRawDumpAttr, sizeof(VI_DUMP_ATTR_S));
        stDumpAttr.bEnable                       = HI_TRUE;
        stDumpAttr.u32Depth                      = u32RawDepth;
        //stDumpAttr.stDumpInfo.enDumpType         = VI_DUMP_TYPE_RAW;
        //stDumpAttr.stDumpInfo.enPixelFormat      = stPixelFrt;
        //stDumpAttr.stDumpInfo.enCompressMode     = enCompressMode;
        //stDumpAttr.stDumpInfo.stCropInfo.bEnable = HI_FALSE;
        s32Ret = HI_MPI_VI_SetPipeDumpAttr(ViPipeId[i], &stDumpAttr);

        if (HI_SUCCESS != s32Ret)
        {
            printf("Set Pipe %d dump attr failed!\n", ViPipeId[i]);
            return s32Ret;
        }

        s32Ret = HI_MPI_VI_GetPipeAttr(ViPipeId[i], &astBackUpPipeAttr[i]);

        if (HI_SUCCESS != s32Ret)
        {
            printf("Get Pipe %d attr failed!\n", vcapPipeHdl);
            return s32Ret;
        }

        memcpy(&stPipeAttr, &astBackUpPipeAttr[i], sizeof(VI_PIPE_ATTR_S));
        stPipeAttr.enCompressMode = enCompressMode;
        s32Ret = HI_MPI_VI_SetPipeAttr(ViPipeId[i], &stPipeAttr);

        if (HI_SUCCESS != s32Ret)
        {
            printf("Set Pipe %d attr failed!\n", vcapPipeHdl);
            return s32Ret;
        }
    }

    sleep(1);
    printf("--> u32PipeNum=%d\n", u32PipeNum);

    if (1 == u32PipeNum || 1 == u32FrmCnt)
    {
        lsc_online_cali_proc(vcapPipeHdl, meshScale, fileIndex,
            u32FrmCnt, u32ByteAlign, u32RatioShow);
    }
    else
    {
        printf("Please check if PipeNum is equal to 1!\n");
        exit(HI_FAILURE);
    }


    for (i = 0; i < u32PipeNum; i++)
    {
        s32Ret = HI_MPI_VI_SetPipeAttr(ViPipeId[i], &astBackUpPipeAttr[i]);

        if (HI_SUCCESS != s32Ret)
        {
            printf("Set Pipe %d attr failed!\n", vcapPipeHdl);
            return s32Ret;
        }

        s32Ret = HI_MPI_VI_SetPipeDumpAttr(ViPipeId[i], &stRawDumpAttr);

        if (HI_SUCCESS != s32Ret)
        {
            printf("Set Pipe %d dump attr failed!\n", vcapPipeHdl);
            return s32Ret;
        }
    }

    return s32Ret;
}

static HI_VOID *lsc_thread(HI_VOID *arg)
{
    prctl(PR_SET_NAME, __func__, 0, 0, 0);

    LSC_CAL_PARAM lscCalParam = *(LSC_CAL_PARAM *)arg;
    lsc_run(lscCalParam.vcapPipeHdl, lscCalParam.meshScale, lscCalParam.fileIndex);

    return HI_NULL;
}

HI_S32 lsc_cal(int argc, char* argv[])
{
    if (argc != 3) {
        printf(
            "\n"
            "*************************************************\n"
            "Usage:lsc_cal [vcapPipeHdl] [meshScale] [fileIndex]\n"
            "e.g  :lsc_cal 0 0 0\n"
            "*************************************************\n"
            "\n");
        return HI_SUCCESS;
    }

    LSC_CAL_PARAM lscCalParam;
    lscCalParam.vcapPipeHdl = atoi(argv[0]);
    lscCalParam.meshScale = atoi(argv[1]);
    lscCalParam.fileIndex = atoi(argv[2]);

    if (lscCalParam.meshScale > 7)
    {
        printf("can't not support scale mode %d, can choose only from 0~7!\n", lscCalParam.meshScale);
        return HI_SUCCESS;
    }

    pthread_attr_t threadattr;
    pthread_attr_init(&threadattr);
    threadattr.stacksize = 0x10000;
    threadattr.inheritsched = PTHREAD_EXPLICIT_SCHED;
    threadattr.schedparam.sched_priority = 5;

    pthread_create(&g_lscCalThread, &threadattr, lsc_thread, &lscCalParam);
    pthread_attr_destroy(&threadattr);
    pthread_join(g_lscCalThread, HI_NULL);

    return HI_SUCCESS;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章