/* 
 | 
 * rk_aiq_algo_aldch_itf.c 
 | 
 * 
 | 
 *  Copyright (c) 2019 Rockchip Corporation 
 | 
 * 
 | 
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 | 
 * you may not use this file except in compliance with the License. 
 | 
 * You may obtain a copy of the License at 
 | 
 * 
 | 
 *      http://www.apache.org/licenses/LICENSE-2.0 
 | 
 * 
 | 
 * Unless required by applicable law or agreed to in writing, software 
 | 
 * distributed under the License is distributed on an "AS IS" BASIS, 
 | 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 | 
 * See the License for the specific language governing permissions and 
 | 
 * limitations under the License. 
 | 
 * 
 | 
 */ 
 | 
  
 | 
#include "rk_aiq_algo_types_int.h" 
 | 
#include "aldch/rk_aiq_algo_aldch_itf.h" 
 | 
#include "aldch/rk_aiq_types_aldch_algo_prvt.h" 
 | 
#include "xcam_log.h" 
 | 
  
 | 
#define LDCH_CUSTOM_MESH "ldch_custom_mesh.bin" 
 | 
  
 | 
RKAIQ_BEGIN_DECLARE 
 | 
  
 | 
static XCamReturn release_ldch_buf(LDCHContext_t* ldchCtx); 
 | 
static XCamReturn alloc_ldch_buf(LDCHContext_t* ldchCtx) 
 | 
{ 
 | 
    release_ldch_buf(ldchCtx); 
 | 
    rk_aiq_share_mem_config_t share_mem_config; 
 | 
    share_mem_config.alloc_param.width =  ldchCtx->dst_width; 
 | 
    share_mem_config.alloc_param.height = ldchCtx->dst_height; 
 | 
    share_mem_config.mem_type = MEM_TYPE_LDCH; 
 | 
    ldchCtx->share_mem_ops->alloc_mem(ldchCtx->share_mem_ops, 
 | 
                                      &share_mem_config, 
 | 
                                      &ldchCtx->share_mem_ctx); 
 | 
    return XCAM_RETURN_NO_ERROR; 
 | 
} 
 | 
  
 | 
static XCamReturn release_ldch_buf(LDCHContext_t* ldchCtx) 
 | 
{ 
 | 
    if (ldchCtx->share_mem_ctx) 
 | 
        ldchCtx->share_mem_ops->release_mem(ldchCtx->share_mem_ctx); 
 | 
  
 | 
    return XCAM_RETURN_NO_ERROR; 
 | 
} 
 | 
  
 | 
static XCamReturn get_ldch_buf(LDCHContext_t* ldchCtx) 
 | 
{ 
 | 
    ldchCtx->ldch_mem_info = (rk_aiq_ldch_share_mem_info_t *) 
 | 
            ldchCtx->share_mem_ops->get_free_item(ldchCtx->share_mem_ctx); 
 | 
    if (ldchCtx->ldch_mem_info == NULL) { 
 | 
        LOGE_ALDCH( "%s(%d): no free ldch buf", __FUNCTION__, __LINE__); 
 | 
        return XCAM_RETURN_ERROR_MEM; 
 | 
    } else { 
 | 
        LOGD_ALDCH( "get ldch buf fd=%d", ldchCtx->ldch_mem_info->fd); 
 | 
        ldchCtx->lut_mapxy = (unsigned short*)ldchCtx->ldch_mem_info->addr; 
 | 
    } 
 | 
  
 | 
    return XCAM_RETURN_NO_ERROR; 
 | 
} 
 | 
  
 | 
static bool 
 | 
read_mesh_from_file(LDCHContext_t* ldchCtx, const char* fileName) 
 | 
{ 
 | 
    FILE* ofp; 
 | 
    ofp = fopen(fileName, "rb"); 
 | 
    if (ofp != NULL) { 
 | 
        unsigned short hpic, vpic, hsize, vsize, hstep, vstep = 0; 
 | 
  
 | 
        fread(&hpic, sizeof(unsigned short), 1, ofp); 
 | 
        fread(&vpic, sizeof(unsigned short), 1, ofp); 
 | 
        fread(&hsize, sizeof(unsigned short), 1, ofp); 
 | 
        fread(&vsize, sizeof(unsigned short), 1, ofp); 
 | 
        fread(&hstep, sizeof(unsigned short), 1, ofp); 
 | 
        fread(&vstep, sizeof(unsigned short), 1, ofp); 
 | 
        //fseek(ofp, 0, SEEK_SET); 
 | 
        LOGW_ALDCH("lut info: [%d-%d-%d-%d-%d-%d]", hpic, vpic, hsize, vsize, hstep, vstep); 
 | 
  
 | 
        ldchCtx->lut_h_size = hsize; 
 | 
        ldchCtx->lut_v_size = vsize; 
 | 
        ldchCtx->lut_mapxy_size = ldchCtx->lut_h_size * ldchCtx->lut_v_size * sizeof(unsigned short); 
 | 
        alloc_ldch_buf(ldchCtx); 
 | 
        get_ldch_buf(ldchCtx); 
 | 
        ldchCtx->lut_h_size = hsize / 2; //word unit 
 | 
  
 | 
        unsigned int num = fread(ldchCtx->lut_mapxy, 1, ldchCtx->lut_mapxy_size, ofp); 
 | 
        fclose(ofp); 
 | 
  
 | 
        if (num != ldchCtx->lut_mapxy_size) { 
 | 
            ldchCtx->ldch_en = 0; 
 | 
            LOGE_ALDCH("mismatched lut calib file"); 
 | 
            return false; 
 | 
        } 
 | 
        LOGW_ALDCH("check calib file, size: %d, num: %d", ldchCtx->lut_mapxy_size, num); 
 | 
    } else { 
 | 
        LOGE_ALDCH("lut calib file %s not exist", fileName); 
 | 
        return false; 
 | 
    } 
 | 
  
 | 
    return true; 
 | 
} 
 | 
  
 | 
#if GENMESH_ONLINE 
 | 
static XCamReturn aiqGenLdchMeshInit(LDCHContext_t* ldchCtx) 
 | 
{ 
 | 
    if (ldchCtx->genLdchMeshInit) { 
 | 
        LOGW_ALDCH("genLDCHMesh has been initialized!!\n"); 
 | 
        get_ldch_buf(ldchCtx); 
 | 
        return XCAM_RETURN_NO_ERROR; 
 | 
    } 
 | 
  
 | 
    ldchCtx->ldchParams.isLdchOld = 1; 
 | 
    ldchCtx->ldchParams.saveMeshX = false; 
 | 
    if (ldchCtx->ldchParams.saveMeshX) 
 | 
        sprintf(ldchCtx->ldchParams.meshPath, "/tmp/"); 
 | 
    genLdchMeshInit(ldchCtx->src_width, ldchCtx->src_height, 
 | 
                    ldchCtx->dst_width, ldchCtx->dst_height, 
 | 
                    ldchCtx->ldchParams, ldchCtx->camCoeff); 
 | 
  
 | 
    ldchCtx->lut_h_size = (ldchCtx->ldchParams.meshSizeW + 1) / 2; //word unit 
 | 
    ldchCtx->lut_v_size = ldchCtx->ldchParams.meshSizeH; 
 | 
    ldchCtx->lut_mapxy_size = ldchCtx->ldchParams.meshSize * sizeof(unsigned short); 
 | 
    LOGI_ALDCH("ldch en %d, h/v size(%dx%d), mapxy size(%d), correct_level: %d", 
 | 
               ldchCtx->ldch_en, 
 | 
               ldchCtx->lut_h_size, 
 | 
               ldchCtx->lut_v_size, 
 | 
               ldchCtx->lut_mapxy_size , 
 | 
               ldchCtx->correct_level); 
 | 
    alloc_ldch_buf(ldchCtx); 
 | 
    get_ldch_buf(ldchCtx); 
 | 
    ldchCtx->genLdchMeshInit = true; 
 | 
  
 | 
    return XCAM_RETURN_NO_ERROR; 
 | 
} 
 | 
  
 | 
static bool aiqGenMesh(LDCHContext_t* ldchCtx) 
 | 
{ 
 | 
    bool success = false; 
 | 
  
 | 
    if (ldchCtx->correct_level == 0) { 
 | 
        char filename[512]; 
 | 
        sprintf(filename, "%s/%s", 
 | 
                ldchCtx->resource_path, 
 | 
                LDCH_CUSTOM_MESH); 
 | 
        success = read_mesh_from_file(ldchCtx, filename); 
 | 
        if (success) 
 | 
            LOGW_ALDCH("read mesh from %s", filename); 
 | 
    } 
 | 
  
 | 
    if (!success) 
 | 
        success = genLDCMeshNLevel(ldchCtx->ldchParams, ldchCtx->camCoeff, 
 | 
                                   ldchCtx->correct_level, ldchCtx->lut_mapxy); 
 | 
  
 | 
    return success; 
 | 
} 
 | 
#endif 
 | 
  
 | 
static XCamReturn 
 | 
updateCalibConfig(RkAiqAlgoCom* params) 
 | 
{ 
 | 
    LDCHHandle_t hLDCH = (LDCHHandle_t)params->ctx->hLDCH; 
 | 
    LDCHContext_t* ldchCtx = (LDCHContext_t*)hLDCH; 
 | 
    RkAiqAlgoConfigAldchInt* rkaiqAldchConfig = (RkAiqAlgoConfigAldchInt*)params; 
 | 
  
 | 
    CalibDbV2_LDCH_t* calib_ldch_db = 
 | 
        (CalibDbV2_LDCH_t*)(CALIBDBV2_GET_MODULE_PTR(rkaiqAldchConfig->rk_com.u.prepare.calibv2, aldch)); 
 | 
    CalibDbV2_Ldch_Param_t* calib_ldch = &calib_ldch_db->param; 
 | 
  
 | 
    ldchCtx->ldch_en = calib_ldch->ldch_en; 
 | 
    memcpy(ldchCtx->meshfile, calib_ldch->meshfile, sizeof(ldchCtx->meshfile)); 
 | 
  
 | 
    ldchCtx->camCoeff.cx = calib_ldch->light_center[0]; 
 | 
    ldchCtx->camCoeff.cy = calib_ldch->light_center[1]; 
 | 
    ldchCtx->camCoeff.a0 = calib_ldch->coefficient[0]; 
 | 
    ldchCtx->camCoeff.a2 = calib_ldch->coefficient[1]; 
 | 
    ldchCtx->camCoeff.a3 = calib_ldch->coefficient[2]; 
 | 
    ldchCtx->camCoeff.a4 = calib_ldch->coefficient[3]; 
 | 
  
 | 
    ldchCtx->correct_level = calib_ldch->correct_level; 
 | 
    ldchCtx->correct_level_max = calib_ldch->correct_level_max; 
 | 
  
 | 
    if (ldchCtx->correct_level_max != 255) 
 | 
        ldchCtx->correct_level = MAP_TO_255LEVEL(ldchCtx->correct_level, ldchCtx->correct_level_max); 
 | 
  
 | 
    aiqGenLdchMeshInit(hLDCH); 
 | 
    bool success = genLDCMeshNLevel(hLDCH->ldchParams, hLDCH->camCoeff, 
 | 
            ldchCtx->correct_level, hLDCH->lut_mapxy); 
 | 
    if (!success) { 
 | 
        LOGE_ALDCH("lut is not exist"); 
 | 
        return XCAM_RETURN_ERROR_PARAM; 
 | 
    } 
 | 
    ldchCtx->isAttribUpdated = true; 
 | 
  
 | 
    LOGI_ALDCH("en(%d), level(%d-%d), coeff(%f, %f, %f, %f, %f, %f)", 
 | 
            calib_ldch->ldch_en, 
 | 
            calib_ldch->correct_level, 
 | 
            calib_ldch->correct_level_max, 
 | 
            calib_ldch->light_center[0], 
 | 
            calib_ldch->light_center[1], 
 | 
            calib_ldch->coefficient[0], 
 | 
            calib_ldch->coefficient[1], 
 | 
            calib_ldch->coefficient[2], 
 | 
            calib_ldch->coefficient[3]); 
 | 
  
 | 
    return XCAM_RETURN_NO_ERROR; 
 | 
} 
 | 
  
 | 
static XCamReturn 
 | 
create_context(RkAiqAlgoContext **context, const AlgoCtxInstanceCfg* cfg) 
 | 
{ 
 | 
    XCamReturn result = XCAM_RETURN_NO_ERROR; 
 | 
  
 | 
    LOG1_ALDCH("%s: (enter)\n", __FUNCTION__ ); 
 | 
    RkAiqAlgoContext *ctx = new RkAiqAlgoContext(); 
 | 
    if (ctx == NULL) { 
 | 
        LOGE_ALDCH( "%s: create aldch context fail!\n", __FUNCTION__); 
 | 
        return XCAM_RETURN_ERROR_MEM; 
 | 
    } 
 | 
    ctx->hLDCH = new LDCHContext_t; 
 | 
    if (ctx->hLDCH == NULL) { 
 | 
        LOGE_ALDCH( "%s: create aldch handle fail!\n", __FUNCTION__); 
 | 
        return XCAM_RETURN_ERROR_MEM; 
 | 
    } 
 | 
    /* setup config */ 
 | 
    memset((void *)(ctx->hLDCH), 0, sizeof(LDCHContext_t) ); 
 | 
  
 | 
    /* return handle */ 
 | 
    *context = ctx; 
 | 
  
 | 
#if GENMESH_ONLINE 
 | 
    ctx->hLDCH->isAttribUpdated = false; 
 | 
    ctx->hLDCH->aldchReadMeshThread = new RKAiqAldchThread(ctx->hLDCH); 
 | 
    /* ctx->hLDCH->aldchReadMeshThread->triger_start(); */ 
 | 
    /* ctx->hLDCH->aldchReadMeshThread->start(); */ 
 | 
#endif 
 | 
  
 | 
    const AlgoCtxInstanceCfgInt* cfg_int = (const AlgoCtxInstanceCfgInt*)cfg; 
 | 
    LDCHHandle_t ldchCtx = ctx->hLDCH; 
 | 
    CalibDbV2_LDCH_t* calib_ldch_db = 
 | 
            (CalibDbV2_LDCH_t*)(CALIBDBV2_GET_MODULE_PTR(cfg_int->calibv2, aldch)); 
 | 
    CalibDbV2_Ldch_Param_t* calib_ldch = &calib_ldch_db->param; 
 | 
  
 | 
    ldchCtx->ldch_en = calib_ldch->ldch_en; 
 | 
    memcpy(ldchCtx->meshfile, calib_ldch->meshfile, sizeof(ldchCtx->meshfile)); 
 | 
#if GENMESH_ONLINE 
 | 
    ldchCtx->camCoeff.cx = calib_ldch->light_center[0]; 
 | 
    ldchCtx->camCoeff.cy = calib_ldch->light_center[1]; 
 | 
    ldchCtx->camCoeff.a0 = calib_ldch->coefficient[0]; 
 | 
    ldchCtx->camCoeff.a2 = calib_ldch->coefficient[1]; 
 | 
    ldchCtx->camCoeff.a3 = calib_ldch->coefficient[2]; 
 | 
    ldchCtx->camCoeff.a4 = calib_ldch->coefficient[3]; 
 | 
    LOGI_ALDCH("(%s) len light center(%.16f, %.16f)\n", 
 | 
            __FUNCTION__, 
 | 
            ldchCtx->camCoeff.cx, ldchCtx->camCoeff.cy); 
 | 
    LOGI_ALDCH("(%s) len coefficient(%.16f, %.16f, %.16f, %.16f)\n", 
 | 
            __FUNCTION__, 
 | 
            ldchCtx->camCoeff.a0, ldchCtx->camCoeff.a2, 
 | 
            ldchCtx->camCoeff.a3, ldchCtx->camCoeff.a4); 
 | 
#endif 
 | 
    ldchCtx->correct_level = calib_ldch->correct_level; 
 | 
    ldchCtx->correct_level_max = calib_ldch->correct_level_max; 
 | 
  
 | 
    if (ldchCtx->correct_level_max != 255) 
 | 
        ldchCtx->correct_level = MAP_TO_255LEVEL(ldchCtx->correct_level, ldchCtx->correct_level_max); 
 | 
  
 | 
    LOGI_ALDCH("ldch en %d, meshfile: %s, correct_level-max: %d-%d from xml file", 
 | 
               calib_ldch->ldch_en, 
 | 
               ldchCtx->meshfile, 
 | 
               ldchCtx->correct_level, 
 | 
               ldchCtx->correct_level_max); 
 | 
  
 | 
    return XCAM_RETURN_NO_ERROR; 
 | 
} 
 | 
  
 | 
static XCamReturn 
 | 
destroy_context(RkAiqAlgoContext *context) 
 | 
{ 
 | 
    LDCHHandle_t hLDCH = (LDCHHandle_t)context->hLDCH; 
 | 
    LDCHContext_t* ldchCtx = (LDCHContext_t*)hLDCH; 
 | 
  
 | 
#if GENMESH_ONLINE 
 | 
    ldchCtx->aldchReadMeshThread->triger_stop(); 
 | 
    ldchCtx->aldchReadMeshThread->stop(); 
 | 
#endif 
 | 
  
 | 
#if GENMESH_ONLINE 
 | 
    genLdchMeshDeInit(ldchCtx->ldchParams); 
 | 
#endif 
 | 
    release_ldch_buf(ldchCtx); 
 | 
    delete context->hLDCH; 
 | 
    context->hLDCH = NULL; 
 | 
    delete context; 
 | 
    context = NULL; 
 | 
    return XCAM_RETURN_NO_ERROR; 
 | 
} 
 | 
  
 | 
static XCamReturn 
 | 
prepare(RkAiqAlgoCom* params) 
 | 
{ 
 | 
    LDCHHandle_t hLDCH = (LDCHHandle_t)params->ctx->hLDCH; 
 | 
    LDCHContext_t* ldchCtx = (LDCHContext_t*)hLDCH; 
 | 
    RkAiqAlgoConfigAldchInt* rkaiqAldchConfig = (RkAiqAlgoConfigAldchInt*)params; 
 | 
  
 | 
    ldchCtx->src_width = params->u.prepare.sns_op_width; 
 | 
    ldchCtx->src_height = params->u.prepare.sns_op_height; 
 | 
    ldchCtx->dst_width = params->u.prepare.sns_op_width; 
 | 
    ldchCtx->dst_height = params->u.prepare.sns_op_height; 
 | 
    ldchCtx->resource_path = rkaiqAldchConfig->resource_path; 
 | 
    ldchCtx->share_mem_ops = rkaiqAldchConfig->mem_ops_ptr; 
 | 
  
 | 
    bool config_calib = !!(params->u.prepare.conf_type & RK_AIQ_ALGO_CONFTYPE_UPDATECALIB); 
 | 
    if (config_calib && ldchCtx->genLdchMeshInit) { 
 | 
        updateCalibConfig(params); 
 | 
        return XCAM_RETURN_NO_ERROR; 
 | 
    } 
 | 
  
 | 
#if GENMESH_ONLINE 
 | 
    // process the new attrib set before prepare 
 | 
    hLDCH->aldchReadMeshThread->triger_stop(); 
 | 
    hLDCH->aldchReadMeshThread->stop(); 
 | 
    if (!hLDCH->aldchReadMeshThread->is_empty()) { 
 | 
        hLDCH->aldchReadMeshThread->clear_attr(); 
 | 
        ldchCtx->isAttribUpdated = true; 
 | 
    } 
 | 
  
 | 
    if (ldchCtx->isAttribUpdated) { 
 | 
        ldchCtx->ldch_en = ldchCtx->user_config.en; 
 | 
        ldchCtx->correct_level = ldchCtx->user_config.correct_level; 
 | 
        ldchCtx->isAttribUpdated = false; 
 | 
    } else { 
 | 
        ldchCtx->user_config.en = ldchCtx->ldch_en; 
 | 
        ldchCtx->user_config.correct_level = ldchCtx->correct_level; 
 | 
    } 
 | 
  
 | 
    hLDCH->aldchReadMeshThread->triger_start(); 
 | 
    hLDCH->aldchReadMeshThread->start(); 
 | 
    if (!ldchCtx->ldch_en) 
 | 
        return XCAM_RETURN_NO_ERROR; 
 | 
  
 | 
    if (aiqGenLdchMeshInit(ldchCtx) == XCAM_RETURN_NO_ERROR) { 
 | 
        bool success = aiqGenMesh(hLDCH); 
 | 
        if (!success) { 
 | 
            LOGW_ALDCH("lut is not exist"); 
 | 
            ldchCtx->ldch_en = 0; 
 | 
        } 
 | 
    } 
 | 
#else 
 | 
    if (!ldchCtx->ldch_en) 
 | 
        return XCAM_RETURN_NO_ERROR; 
 | 
  
 | 
    char filename[512]; 
 | 
    sprintf(filename, "%s/%s/mesh_level%d.bin", 
 | 
            ldchCtx->resource_path, 
 | 
            ldchCtx->meshfile, 
 | 
            ldchCtx->correct_level); 
 | 
    bool ret = read_mesh_from_file(ldchCtx, filename); 
 | 
    if (!ret) 
 | 
        ldchCtx->ldch_en = 0; 
 | 
#endif 
 | 
  
 | 
    return XCAM_RETURN_NO_ERROR; 
 | 
} 
 | 
  
 | 
static XCamReturn 
 | 
pre_process(const RkAiqAlgoCom* inparams, RkAiqAlgoResCom* outparams) 
 | 
{ 
 | 
    return XCAM_RETURN_NO_ERROR; 
 | 
} 
 | 
  
 | 
static XCamReturn 
 | 
processing(const RkAiqAlgoCom* inparams, RkAiqAlgoResCom* outparams) 
 | 
{ 
 | 
    LDCHHandle_t hLDCH = (LDCHHandle_t)inparams->ctx->hLDCH; 
 | 
    LDCHContext_t* ldchCtx = (LDCHContext_t*)hLDCH; 
 | 
    RkAiqAlgoProcResAldchInt* ldchPreOut = (RkAiqAlgoProcResAldchInt*)outparams; 
 | 
  
 | 
    if (inparams->u.proc.init) { 
 | 
        ldchPreOut->ldch_result.update = 1; 
 | 
    } else { 
 | 
        if (ldchCtx->isAttribUpdated) { 
 | 
            ldchCtx->isAttribUpdated = false; 
 | 
            ldchPreOut->ldch_result.update = 1; 
 | 
        } else { 
 | 
            ldchPreOut->ldch_result.update = 0; 
 | 
        } 
 | 
  
 | 
        LOGV_ALDCH("(%s) en(%d), level(%d), user en(%d), level(%d), result update(%d)\n", 
 | 
                __FUNCTION__, 
 | 
                ldchCtx->ldch_en, 
 | 
                ldchCtx->correct_level, 
 | 
                ldchCtx->user_config.en, 
 | 
                ldchCtx->user_config.correct_level, 
 | 
                ldchPreOut->ldch_result.update); 
 | 
    } 
 | 
  
 | 
    if (ldchPreOut->ldch_result.update) { 
 | 
        ldchPreOut->ldch_result.sw_ldch_en = ldchCtx->ldch_en; 
 | 
        ldchPreOut->ldch_result.lut_h_size = ldchCtx->lut_h_size; 
 | 
        ldchPreOut->ldch_result.lut_v_size = ldchCtx->lut_v_size; 
 | 
        ldchPreOut->ldch_result.lut_map_size = ldchCtx->lut_mapxy_size; 
 | 
        if (ldchCtx->lut_mapxy != NULL && ldchCtx->ldch_en) { 
 | 
            if (ldchCtx->ldch_mem_info == NULL) { 
 | 
                LOGE_ALDCH("%s: no available ldch buf!", __FUNCTION__); 
 | 
                ldchPreOut->ldch_result.update = 0; 
 | 
                return XCAM_RETURN_NO_ERROR; 
 | 
            } 
 | 
            ldchPreOut->ldch_result.lut_mapxy_buf_fd = ldchCtx->ldch_mem_info->fd; 
 | 
            ldchCtx->ldch_mem_info->state[0] = 1; //mark that this buf is using. 
 | 
        } 
 | 
    } 
 | 
  
 | 
    return XCAM_RETURN_NO_ERROR; 
 | 
} 
 | 
  
 | 
static XCamReturn 
 | 
post_process(const RkAiqAlgoCom* inparams, RkAiqAlgoResCom* outparams) 
 | 
{ 
 | 
    return XCAM_RETURN_NO_ERROR; 
 | 
} 
 | 
  
 | 
RkAiqAlgoDescription g_RkIspAlgoDescAldch = { 
 | 
    .common = { 
 | 
        .version = RKISP_ALGO_ALDCH_VERSION, 
 | 
        .vendor  = RKISP_ALGO_ALDCH_VENDOR, 
 | 
        .description = RKISP_ALGO_ALDCH_DESCRIPTION, 
 | 
        .type    = RK_AIQ_ALGO_TYPE_ALDCH, 
 | 
        .id      = 0, 
 | 
        .create_context  = create_context, 
 | 
        .destroy_context = destroy_context, 
 | 
    }, 
 | 
    .prepare = prepare, 
 | 
    .pre_process = pre_process, 
 | 
    .processing = processing, 
 | 
    .post_process = post_process, 
 | 
}; 
 | 
  
 | 
RKAIQ_END_DECLARE 
 | 
  
 | 
  
 | 
bool RKAiqAldchThread::loop() 
 | 
{ 
 | 
    XCamReturn ret = XCAM_RETURN_NO_ERROR; 
 | 
    ENTER_ANALYZER_FUNCTION(); 
 | 
  
 | 
    const static int32_t timeout = -1; 
 | 
    SmartPtr<rk_aiq_ldch_cfg_t> attrib = mAttrQueue.pop (timeout); 
 | 
  
 | 
    if (!attrib.ptr()) { 
 | 
        LOGW_ANALYZER("RKAiqAldchThread got empty attrib, stop thread"); 
 | 
        return false; 
 | 
    } 
 | 
#if GENMESH_ONLINE 
 | 
    if (attrib->en && (hLDCH->ldch_en != attrib->en || \ 
 | 
        attrib->correct_level != hLDCH->correct_level)) { 
 | 
        aiqGenLdchMeshInit(hLDCH); 
 | 
        bool success = aiqGenMesh(hLDCH); 
 | 
        if (!success) 
 | 
            LOGW_ALDCH("lut is not exist"); 
 | 
    } 
 | 
    hLDCH->ldch_en = hLDCH->user_config.en; 
 | 
    hLDCH->correct_level = hLDCH->user_config.correct_level; 
 | 
#endif 
 | 
    if (ret == XCAM_RETURN_NO_ERROR) { 
 | 
        hLDCH->isAttribUpdated = true; 
 | 
        LOGV_ANALYZER("ldch en(%d), level(%d)\n", hLDCH->ldch_en, hLDCH->correct_level); 
 | 
        return true; 
 | 
    } 
 | 
  
 | 
    LOGE_ANALYZER("RKAiqAldchThread failed to read mesh table!"); 
 | 
  
 | 
    EXIT_ANALYZER_FUNCTION(); 
 | 
  
 | 
    return false; 
 | 
} 
 |