/* * rk_aiq_accm_algo.cpp * for rockchip v2.0.0 * * 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. * */ /* for rockchip v2.0.0*/ #include "accm/rk_aiq_accm_algo.h" #include "xcam_log.h" #include "interpolation.h" RKAIQ_BEGIN_DECLARE XCamReturn Swinfo_wbgain_init(float awbGain[2], const CalibDbV2_Ccm_Tuning_Para_t *pCalib, const char* illuName) { XCamReturn ret = XCAM_RETURN_NO_ERROR; LOG1_ACCM("%s(%d): (enter)\n", __FUNCTION__, __LINE__); if (pCalib == NULL) { ret = XCAM_RETURN_ERROR_PARAM; LOGE_ACCM("%s(%d): invalid input params\n", __FUNCTION__, __LINE__); return ret; } bool lsFound = false; for(int i = 0; i < pCalib->aCcmCof_len; i++) { if(strcmp(pCalib->aCcmCof[i].name, illuName) == 0) { awbGain[0] = pCalib->aCcmCof[i].awbGain[0]; awbGain[1] = pCalib->aCcmCof[i].awbGain[1]; lsFound = true; LOGD_ACCM("%s: accm lsForFirstFrame:%s", __FUNCTION__, pCalib->aCcmCof[i].name); break; } } if(pCalib->aCcmCof_len> 0 && lsFound == false) { awbGain[0] = pCalib->aCcmCof[0].awbGain[0]; awbGain[1] = pCalib->aCcmCof[0].awbGain[1]; LOGD_ACCM("%s: accm lsForFirstFrame:%s", __FUNCTION__, pCalib->aCcmCof[0].name); } LOGV_ACCM("%s: accm illunum:%d", __FUNCTION__, pCalib->aCcmCof_len); LOG1_ACCM( "%s(%d): (exit)\n", __FUNCTION__, __LINE__); return ret; } XCamReturn illuminant_index_estimation_ccm(int light_num, const CalibDbV2_Ccm_Accm_Cof_Para_t illAll[], float awbGain[2], int* illuminant_index) { LOG1_ACCM( "%s: (enter)\n", __FUNCTION__); float minDist = 9999999; float dist[8]; float nRG, nBG; nRG = awbGain[0]; nBG = awbGain[1]; *illuminant_index = 0; XCamReturn ret = XCAM_RETURN_ERROR_FAILED; for(int i = 0; i < light_num; i++) { dist[i] = sqrt((nRG - illAll[i].awbGain[0]) * (nRG - illAll[i].awbGain[0]) + (nBG - illAll[i].awbGain[1]) * (nBG - illAll[i].awbGain[1])); if(dist[i] < minDist) { minDist = dist[i]; *illuminant_index = i; ret = XCAM_RETURN_NO_ERROR; } } if(ret != XCAM_RETURN_NO_ERROR) { LOGE_ACCM("fail to estimate illuminant!!!\n"); } LOGD_ACCM( "wbGain:%f,%f, estimation illuminant is %s(%d) \n", awbGain[0], awbGain[1], illAll[*illuminant_index].name, *illuminant_index); LOG1_ACCM( "%s: (exit)\n", __FUNCTION__); return ret; } XCamReturn illuminant_index_candidate_ccm(int light_num, const CalibDbV2_Ccm_Accm_Cof_Para_t illAll[], float awbGain[2], char* default_illu, float prob_limit, const float weight_rb[2], float* prob) { LOG1_ACCM( "%s: (enter)\n", __FUNCTION__); float dist[8]; float nRG, nBG; nRG = awbGain[0]; nBG = awbGain[1]; float wr = weight_rb[0]; float wb = weight_rb[1]; XCamReturn ret = XCAM_RETURN_ERROR_FAILED; if (light_num == 0) { LOGE_ACCM(" Illuminant Profile does not exit !!!\n"); return ret; } LOGD_ACCM( "==================Illu Probability=========================\n"); LOGD_ACCM( " wbGain: %f, %f \n",awbGain[0], awbGain[1] ); memset(prob, 0, light_num*sizeof(float)); if (light_num == 1) { prob[0] =1; LOGD_ACCM( " Only one illuminant profile: Illu Name is %s, prob = %f \n", illAll[0].name, prob[0]); ret = XCAM_RETURN_NO_ERROR;} else { float mean_dist = 0; int idx = 0; float minDist = 9999999; int default_illu_idx = 0; for(int i = 0; i < light_num; i++) { dist[i] = sqrt((nRG - illAll[i].awbGain[0]) * (nRG - illAll[i].awbGain[0])*wr + (nBG - illAll[i].awbGain[1]) * (nBG - illAll[i].awbGain[1])*wb); if (strcmp( default_illu, illAll[i].name) == 0) default_illu_idx = i; if(dist[i] < minDist) { minDist = dist[i]; idx = i; } mean_dist = mean_dist + dist[i]; } if (minDist < illAll[idx].minDist) { prob[idx] = 1; LOGD_ACCM( " Illu Name: %s(%d), dist = %f, prob = %f \n", illAll[idx].name, idx, dist[idx], prob[idx]); LOGD_ACCM( "=======================================================\n"); ret = XCAM_RETURN_NO_ERROR; LOG1_ACCM( "%s: (exit)\n", __FUNCTION__); return ret; } float sigma = 0; mean_dist = mean_dist/light_num; for(int i = 0; i < light_num; i++) sigma = sigma + (dist[i] - mean_dist)* (dist[i] - mean_dist); sigma = sigma/light_num; if (fabs(sigma)>DIVMIN) { float sum_prob = 0; for(int i = 0; i < light_num; i++) { prob[i] = exp(-0.5*dist[i]*dist[i]/sigma); sum_prob = sum_prob + prob[i]; } // normalize prob float new_sum_prob = 0; LOGD_ACCM( " prob_limit = %f \n",prob_limit); for(int i = 0; i < light_num; i++) { float prob_tmp; prob_tmp = prob[i]/sum_prob; LOGD_ACCM( " Illu Name: %s(%d), dist = %f, ori prob = %f \n", illAll[i].name, i, dist[i], prob_tmp); if (prob_tmp < prob_limit ) { prob[i] = 0; } new_sum_prob += prob[i]; } LOGD_ACCM( "------------------------------------\n"); if (fabs(new_sum_prob) max_prob){ max_prob = prob[i]; maxprob_idx = i; } } memset(prob, 0, light_num*sizeof(float)); prob[maxprob_idx] = 1; LOGD_ACCM(" pick max prob illu : %s(%d), dist = %f, ori prob = %f \n", illAll[maxprob_idx].name, maxprob_idx, dist[maxprob_idx], prob[maxprob_idx]); } else { float *prob_test = (float*)malloc(light_num*sizeof(float)); memset(prob_test, 0, light_num*sizeof(float)); float fsum_prob = 0; for(int i = 0; i < light_num; i++) { prob_test[i] = prob[i]/new_sum_prob; if (prob_test[i]<0.333333) prob_test[i] = 0; fsum_prob += prob_test[i]; } if (fabs(fsum_prob)saturation < pCcmProfiles[j + 1]->saturation) { const CalibDbV2_Ccm_Ccm_Matrix_Para_t* temp = pCcmProfiles[j]; pCcmProfiles[j] = pCcmProfiles[j + 1]; pCcmProfiles[j + 1] = temp; } } } return (XCAM_RETURN_NO_ERROR); } XCamReturn pCcmMatrixAll_init(accm_context_t* accm_context, const CalibDbV2_Ccm_Tuning_Para_t *pCalib) { XCamReturn ret = XCAM_RETURN_NO_ERROR; LOG1_ACCM("%s(%d): (enter)\n", __FUNCTION__, __LINE__); if (pCalib == NULL) { ret = XCAM_RETURN_ERROR_PARAM; LOGE_ACCM("%s(%d): invalid input params\n", __FUNCTION__, __LINE__); return ret; } //Config pCcmMatrixAll (normal and hdr) // 1) get and reorder para for(int i = 0; i < pCalib->aCcmCof_len; i++) { for (int j = 0; j < pCalib->aCcmCof[i].matrixUsed_len; j++) { char name[CCM_PROFILE_NAME]; sprintf(name, "%s", pCalib->aCcmCof[i].matrixUsed[j]); const CalibDbV2_Ccm_Ccm_Matrix_Para_t* pCcmMatrixProfile = NULL; // get a ccm-profile from database ret = CamCalibDbGetCcmProfileByName(pCalib, name, &pCcmMatrixProfile); RETURN_RESULT_IF_DIFFERENT(ret, XCAM_RETURN_NO_ERROR); // store ccm-profile in pointer array accm_context->pCcmMatrixAll[i][j] = pCcmMatrixProfile; LOGV_ACCM("CCM name %s coef:%f,%f,%f %f,%f,%f %f,%f,%f \n", name, accm_context->pCcmMatrixAll[i][j]->ccMatrix[0], accm_context->pCcmMatrixAll[i][j]->ccMatrix[1], accm_context->pCcmMatrixAll[i][j]->ccMatrix[2], accm_context->pCcmMatrixAll[i][j]->ccMatrix[3], accm_context->pCcmMatrixAll[i][j]->ccMatrix[4], accm_context->pCcmMatrixAll[i][j]->ccMatrix[5], accm_context->pCcmMatrixAll[i][j]->ccMatrix[6], accm_context->pCcmMatrixAll[i][j]->ccMatrix[7], accm_context->pCcmMatrixAll[i][j]->ccMatrix[8]); LOGV_ACCM("CCM name %s off:%f,%f,%f \n", name, accm_context->pCcmMatrixAll[i][j]->ccOffsets[0], accm_context->pCcmMatrixAll[i][j]->ccOffsets[1], accm_context->pCcmMatrixAll[i][j]->ccOffsets[2]); } // order ccm-profiles by saturation ret = AwbOrderCcmProfilesBySaturation(accm_context->pCcmMatrixAll[i], pCalib->aCcmCof[i].matrixUsed_len); //RETURN_RESULT_IF_DIFFERENT(result, XCAM_RETURN_NO_ERROR); } LOG1_ACCM( "%s(%d): (exit)\n", __FUNCTION__, __LINE__); return ret; } static XCamReturn SatSelectCcmProfiles ( const float fSaturation, int32_t no_ccm, const CalibDbV2_Ccm_Ccm_Matrix_Para_t* pCcmProfiles[], const CalibDbV2_Ccm_Ccm_Matrix_Para_t** pCcmProfile1, const CalibDbV2_Ccm_Ccm_Matrix_Para_t** pCcmProfile2 ) { XCamReturn XCamReturn = XCAM_RETURN_NO_ERROR; if ((no_ccm == 0) || (pCcmProfiles == NULL) || (pCcmProfile1 == NULL) || (pCcmProfile2 == NULL)) { return (XCAM_RETURN_ERROR_PARAM); } if (fSaturation >= pCcmProfiles[0]->saturation) { *pCcmProfile1 = pCcmProfiles[0]; *pCcmProfile2 = NULL; LOGV_ACCM( "select:%s \n", (*pCcmProfile1)->name); XCamReturn = XCAM_RETURN_ERROR_OUTOFRANGE; } else { int32_t nLast = no_ccm - 1; if (fSaturation <= pCcmProfiles[nLast]->saturation) { *pCcmProfile1 = pCcmProfiles[nLast]; *pCcmProfile2 = NULL; LOGV_ACCM( "select:%s \n", (*pCcmProfile1)->name); XCamReturn = XCAM_RETURN_ERROR_OUTOFRANGE; } else { uint16_t n = 0; /* find the segment */ while ((fSaturation <= pCcmProfiles[n]->saturation) && (n <= nLast)) { n++; } if (n > 0) n--; *pCcmProfile1 = pCcmProfiles[n]; *pCcmProfile2 = pCcmProfiles[n + 1]; } } return (XCamReturn); } /****************************************************************************** * InterpolateMatrices *****************************************************************************/ static XCamReturn SatInterpolateMatrices ( const float fSat, const CalibDbV2_Ccm_Ccm_Matrix_Para_t* pCcProfileA, const CalibDbV2_Ccm_Ccm_Matrix_Para_t* pCcProfileB, float* pResMatrix ) { XCamReturn iXCamReturn = XCAM_RETURN_ERROR_PARAM; if ((pCcProfileA != NULL) && (pCcProfileA != NULL) && (pResMatrix != NULL)) { const float *pMatrixA = pCcProfileA->ccMatrix; const float *pMatrixB = pCcProfileB->ccMatrix; float fSatA = pCcProfileA->saturation; float fSatB = pCcProfileB->saturation; float f1 = ( fSatB - fSat ) / ( fSatB - fSatA ); // test: if fSat == fSatA => f1 = 1 => choose A: ok float f2 = 1.0f - f1; int i; for ( i = 0; i < 9; i++) { pResMatrix[i] = f1 * pMatrixA[i] + f2 * pMatrixB[i]; } iXCamReturn = XCAM_RETURN_NO_ERROR; } return (iXCamReturn); } /****************************************************************************** * InterpolateMatrices *****************************************************************************/ static XCamReturn SatInterpolateOffset ( const float fSat, const CalibDbV2_Ccm_Ccm_Matrix_Para_t* pCcProfileA, const CalibDbV2_Ccm_Ccm_Matrix_Para_t* pCcProfileB, float *pResOffset ) { XCamReturn result = XCAM_RETURN_ERROR_PARAM; if ( (pCcProfileA != NULL) && (pCcProfileB != NULL) && (pResOffset != NULL) ) { const float *pOffsetA = pCcProfileA->ccOffsets; const float *pOffsetB = pCcProfileB->ccOffsets; float fSatA = pCcProfileA->saturation; float fSatB = pCcProfileB->saturation; float f1 = ( fSatB - fSat ) / ( fSatB - fSatA ); // test: if fSat == fSatA => f1 = 1 => choose A: ok float f2 = 1.0f - f1; pResOffset[CAM_3CH_COLOR_COMPONENT_RED] = f1 * pOffsetA[CAM_3CH_COLOR_COMPONENT_RED] + f2 * pOffsetB[CAM_3CH_COLOR_COMPONENT_RED]; pResOffset[CAM_3CH_COLOR_COMPONENT_GREEN] = f1 * pOffsetA[CAM_3CH_COLOR_COMPONENT_GREEN] + f2 * pOffsetB[CAM_3CH_COLOR_COMPONENT_GREEN]; pResOffset[CAM_3CH_COLOR_COMPONENT_BLUE] = f1 * pOffsetA[CAM_3CH_COLOR_COMPONENT_BLUE] + f2 * pOffsetB[CAM_3CH_COLOR_COMPONENT_BLUE]; result = XCAM_RETURN_NO_ERROR; } return ( result ); } /****************************************************************************** * Damping *****************************************************************************/ static XCamReturn Damping ( const float damp, /**< damping coefficient */ float *pMatrixUndamped, /**< undamped new computed matrices */ float *pMatrixDamped, /**< old matrices and result */ float *pOffsetUndamped, /**< undamped new computed offsets */ float *pOffsetDamped /**< old offset and result */ ) { XCamReturn result = XCAM_RETURN_ERROR_PARAM; if ( (pMatrixUndamped != NULL) && (pMatrixDamped != NULL) && (pOffsetUndamped != NULL) && (pOffsetDamped != NULL) ) { int32_t i; float f = (1.0f - damp); /* calc. damped cc matrix */ for( i = 0; i < 9; i++ ) { pMatrixDamped[i] = (damp * pMatrixDamped[i]) + (f * pMatrixUndamped[i]); } /* calc. damped cc offsets */ pOffsetDamped[CAM_3CH_COLOR_COMPONENT_RED] = (damp * pOffsetDamped[CAM_3CH_COLOR_COMPONENT_RED]) + (f * pOffsetUndamped[CAM_3CH_COLOR_COMPONENT_RED]); pOffsetDamped[CAM_3CH_COLOR_COMPONENT_GREEN] = (damp * pOffsetDamped[CAM_3CH_COLOR_COMPONENT_GREEN]) + (f * pOffsetUndamped[CAM_3CH_COLOR_COMPONENT_GREEN]); pOffsetDamped[CAM_3CH_COLOR_COMPONENT_BLUE] = (damp * pOffsetDamped[CAM_3CH_COLOR_COMPONENT_BLUE]) + (f * pOffsetUndamped[CAM_3CH_COLOR_COMPONENT_BLUE]); result = XCAM_RETURN_NO_ERROR; } LOGD_ACCM( "dampfactor:%f", damp); LOGD_ACCM( " undampedCcmMatrix: %f,%f,%f,%f,%f,%f,%f,%f,%f undampedCcOffset:%f,%f,%f \n", pMatrixUndamped[0], pMatrixUndamped[1], pMatrixUndamped[2], pMatrixUndamped[3], pMatrixUndamped[4], pMatrixUndamped[5], pMatrixUndamped[6], pMatrixUndamped[7], pMatrixUndamped[8], pOffsetUndamped[0], pOffsetUndamped[1], pOffsetUndamped[2] ); LOGD_ACCM( " dampedCcmMatrix: %f,%f,%f,%f,%f,%f,%f,%f,%f dampedCcOffset:%f,%f,%f \n", pMatrixDamped[0], pMatrixDamped[1], pMatrixDamped[2], pMatrixDamped[3], pMatrixDamped[4], pMatrixDamped[5], pMatrixDamped[6], pMatrixDamped[7], pMatrixDamped[8], pOffsetDamped[0], pOffsetDamped[1], pOffsetDamped[2] ); return ( result ); } void Saturationadjust(float fScale, accm_handle_t hAccm ) { float *pccMatrixA; float Matrix_tmp[9]; float flevel1 = hAccm->accmRest.color_saturation_level; if (fScale < DIVMIN) { if(fabs((flevel1-50))>DIVMIN){ LOGW_ACCM("fSclae is %f , so saturation adjust bypass\n", fScale); } } else { flevel1 = (flevel1 - 50) / 50 + 1; LOGV_ACCM("Satura: %f \n", flevel1); pccMatrixA = hAccm->accmRest.undampedCcmMatrix; memcpy(&Matrix_tmp, pccMatrixA, sizeof(Matrix_tmp)); float *pccMatrixB; pccMatrixB = Matrix_tmp; /* M = (M0 - E) * fscale + E M' = ycbcr2rgb[ sat_matrix * rgb2ycbcr(M) ] M1 = (M' - E) / fscale + E */ if ( (pccMatrixA != NULL) && (pccMatrixB != NULL) ) { for(int i =0; i < 9; i++) { if (i == 0 || i == 4 || i == 8){ pccMatrixA[i] = (pccMatrixA[i] - 1)*fScale+1; } else{ pccMatrixA[i] = pccMatrixA[i]*fScale; } } pccMatrixB[0] = 0.299 * pccMatrixA[0] + 0.587 * pccMatrixA[3] + 0.114 * pccMatrixA[6]; pccMatrixB[1] = 0.299 * pccMatrixA[1] + 0.587 * pccMatrixA[4] + 0.114 * pccMatrixA[7]; pccMatrixB[2] = 0.299 * pccMatrixA[2] + 0.587 * pccMatrixA[5] + 0.114 * pccMatrixA[8]; pccMatrixB[3] = -0.1687 * pccMatrixA[0] - 0.3313 * pccMatrixA[3] + 0.5 * pccMatrixA[6]; pccMatrixB[4] = -0.1687 * pccMatrixA[1] - 0.3313 * pccMatrixA[4] + 0.5 * pccMatrixA[7]; pccMatrixB[5] = -0.1687 * pccMatrixA[2] - 0.3313 * pccMatrixA[5] + 0.5 * pccMatrixA[8]; pccMatrixB[6] = 0.5 * pccMatrixA[0] - 0.4187 * pccMatrixA[3] - 0.0813 * pccMatrixA[6]; pccMatrixB[7] = 0.5 * pccMatrixA[1] - 0.4187 * pccMatrixA[4] - 0.0813 * pccMatrixA[7]; pccMatrixB[8] = 0.5 * pccMatrixA[2] - 0.4187 * pccMatrixA[5] - 0.0813 * pccMatrixA[8]; for(int i = 3; i < 9; i++) { pccMatrixB[i] = flevel1 * pccMatrixB[i]; } pccMatrixA[0] = 1 * pccMatrixB[0] + 0 * pccMatrixB[3] + 1.402 * pccMatrixB[6]; pccMatrixA[1] = 1 * pccMatrixB[1] + 0 * pccMatrixB[4] + 1.402 * pccMatrixB[7]; pccMatrixA[2] = 1 * pccMatrixB[2] + 0 * pccMatrixB[5] + 1.402 * pccMatrixB[8]; pccMatrixA[3] = 1 * pccMatrixB[0] - 0.34414 * pccMatrixB[3] - 0.71414 * pccMatrixB[6]; pccMatrixA[4] = 1 * pccMatrixB[1] - 0.34414 * pccMatrixB[4] - 0.71414 * pccMatrixB[7]; pccMatrixA[5] = 1 * pccMatrixB[2] - 0.34414 * pccMatrixB[5] - 0.71414 * pccMatrixB[8]; pccMatrixA[6] = 1 * pccMatrixB[0] + 1.772 * pccMatrixB[3] + 0 * pccMatrixB[6]; pccMatrixA[7] = 1 * pccMatrixB[1] + 1.772 * pccMatrixB[4] + 0 * pccMatrixB[7]; pccMatrixA[8] = 1 * pccMatrixB[2] + 1.772 * pccMatrixB[5] + 0 * pccMatrixB[8]; for(int i =0; i < 9; i++) { if (i == 0 || i == 4 || i == 8){ pccMatrixA[i] = (pccMatrixA[i] - 1)/fScale+1; } else{ pccMatrixA[i] = pccMatrixA[i]/fScale; } } } } } XCamReturn CamCalibDbGetCcmProfileByName(const CalibDbV2_Ccm_Tuning_Para_t *calibCcm, char* name, const CalibDbV2_Ccm_Ccm_Matrix_Para_t **pCcmMatrixProfile) { LOG1_ACCM("%s: (enter)\n", __FUNCTION__); XCamReturn ret = XCAM_RETURN_ERROR_FAILED; for(int i = 0; i matrixAll_len; i++) { if(strcmp(calibCcm->matrixAll[i].name, name) == 0) { *pCcmMatrixProfile = &calibCcm->matrixAll[i]; ret = XCAM_RETURN_NO_ERROR; break; } } if(ret != XCAM_RETURN_NO_ERROR) { LOGE_ACCM("can't find %s in matrixAll \n", name); } LOG1_ACCM("%s: (exit)\n", __FUNCTION__); return ret; } static void UpdateIlluProbList(List *l, int illu, float prob, int listMaxSize) { prob_node_t *pCurNode; int sizeList; if(listMaxSize == 0) { return; } pCurNode = (prob_node_t*)malloc(sizeof(prob_node_t)); pCurNode->value = illu; pCurNode->prob = prob; ListPrepareItem(pCurNode); ListAddTail(l, pCurNode); sizeList = ListNoItems(l); if (sizeList > listMaxSize) { prob_node_t *pDelNode; pDelNode = (prob_node_t *)ListRemoveHead(l); free(pDelNode); } } static void StableProbEstimation(List l, int listSize, int count, int illuNum, float* probSet) { int sizeList = ListNoItems(&l); if(sizeList < listSize || listSize == 0) { return; } float *prob_tmp = (float*)malloc(illuNum*sizeof(float)); memset(prob_tmp, 0, illuNum*sizeof(float)); List *pNextNode = ListHead(&l); while (NULL != pNextNode) { prob_node_t *pL; pL = (prob_node_t*)pNextNode; prob_tmp[pL->value] += pL->prob; pNextNode = pNextNode->p_next; } for(int i=0; ivalue = illu; ListPrepareItem(pCurNode); ListAddTail(l, pCurNode); sizeList = ListNoItems(l); if (sizeList > listMaxSize) { illu_node_t *pDelNode; pDelNode = (illu_node_t *)ListRemoveHead(l); free(pDelNode); } } static void StableIlluEstimation(List l, int listSize, int illuNum, float varianceLuma, float varianceLumaTh, bool awbConverged, int preIllu, int *newIllu) { int sizeList = ListNoItems(&l); if(sizeList < listSize || listSize == 0) { return; } /*if( awbConverged) { *newIllu = preIllu; LOGD_ALSC("awb is converged , reserve the last illumination(%d) \n", preIllu ); return; }*/ /*if( varianceLuma <= varianceLumaTh) { *newIllu = preIllu; LOGD_ACCM("varianceLuma %f < varianceLumaTh %f , reserve the last illumination(%d) \n", varianceLuma,varianceLumaTh,preIllu ); return; }*/ List *pNextNode = ListHead(&l); illu_node_t *pL; int *illuSet = (int*)malloc(illuNum*sizeof(int)); memset(illuSet, 0, illuNum*sizeof(int)); while (NULL != pNextNode) { pL = (illu_node_t*)pNextNode; illuSet[pL->value]++; pNextNode = pNextNode->p_next; } int max_count = 0; for(int i=0; i max_count){ max_count = illuSet[i]; *newIllu = i; } } free(illuSet); LOGV_ACCM("varianceLuma %f, varianceLumaTh %f final estmination illu is %d\n", varianceLuma,varianceLumaTh,*newIllu ); } XCamReturn AccmAutoConfig ( accm_handle_t hAccm ) { LOG1_ACCM("%s: (enter)\n", __FUNCTION__); XCamReturn ret = XCAM_RETURN_NO_ERROR; const CalibDbV2_Ccm_Accm_Cof_Para_t* pDomIlluProfile = NULL; const CalibDbV2_Ccm_Ccm_Matrix_Para_t* pCcmProfile1 = NULL; const CalibDbV2_Ccm_Ccm_Matrix_Para_t* pCcmProfile2 = NULL; if (hAccm == NULL) { return XCAM_RETURN_ERROR_PARAM; } const CalibDbV2_Ccm_Para_V2_t * pCcm = NULL; float sensorGain = hAccm->accmSwInfo.sensorGain; float fSaturation; if (hAccm->mCurAtt.mode == RK_AIQ_CCM_MODE_TOOL){ pCcm = &hAccm->mCurAtt.stTool; ret = pCcmMatrixAll_init(hAccm, &hAccm->mCurAtt.stTool.TuningPara); RETURN_RESULT_IF_DIFFERENT(ret, XCAM_RETURN_NO_ERROR); } else { pCcm = hAccm->calibV2Ccm; } if (hAccm->update || hAccm->updateAtt) { LOGD_ACCM("Illu Probability Estimation Enable: %d \n", pCcm->TuningPara.illu_estim.interp_enable); if (pCcm->TuningPara.illu_estim.interp_enable) { //1) estimate illuminant prob float probfSaturation = 0; memset(hAccm->accmRest.undampedCcmMatrix, 0, sizeof(hAccm->accmRest.undampedCcmMatrix)); memset(hAccm->accmRest.undampedCcOffset, 0, sizeof(hAccm->accmRest.undampedCcOffset)); float *prob = (float*)malloc(pCcm->TuningPara.aCcmCof_len*sizeof(float)); ret = illuminant_index_candidate_ccm(pCcm->TuningPara.aCcmCof_len, pCcm->TuningPara.aCcmCof, hAccm->accmSwInfo.awbGain, pCcm->TuningPara.illu_estim.default_illu, pCcm->TuningPara.illu_estim.prob_limit, pCcm->TuningPara.illu_estim.weightRB, prob); RETURN_RESULT_IF_DIFFERENT(ret, XCAM_RETURN_NO_ERROR); // calculate stable prob int problistsize = pCcm->TuningPara.illu_estim.frame_no*pCcm->TuningPara.aCcmCof_len; for (int i = 0; i < pCcm->TuningPara.aCcmCof_len; i++) UpdateIlluProbList(&hAccm->accmRest.problist, i, prob[i], problistsize); int frames = (int)hAccm->count > (pCcm->TuningPara.illu_estim.frame_no-1) ? pCcm->TuningPara.illu_estim.frame_no : hAccm->count;//todo //LOGE_ACCM( " cashed frame No: %d, ListSize = %d \n", frames, ListNoItems(&hAccm->accmRest.problist)); LOGD_ACCM( "==================stable Illu Probability=========================\n"); StableProbEstimation(hAccm->accmRest.problist, problistsize, frames, pCcm->TuningPara.aCcmCof_len, prob); LOGD_ACCM( "============================================================\n"); // 2) all illuminant do interp by fSaturation float undampedCcmMatrix[9]; float undampedCcOffset[3]; for (int i = 0; i < pCcm->TuningPara.aCcmCof_len; i++){ if (fabs(prob[i])TuningPara.aCcmCof[i]; interpolation(pDomIlluProfile->gain_sat_curve.gains, pDomIlluProfile->gain_sat_curve.sat, 4, sensorGain, &fSaturation); // (2) interp CCM matrix and offset ret = SatSelectCcmProfiles(fSaturation, pDomIlluProfile->matrixUsed_len, hAccm->pCcmMatrixAll[i], &pCcmProfile1, &pCcmProfile2); if (ret == XCAM_RETURN_NO_ERROR) { XCamReturn ret1 = XCAM_RETURN_NO_ERROR; if (pCcmProfile1 && pCcmProfile2) LOGV_ACCM("No.%d Illu : %s interp by sat, final fSaturation: %f (%f .. %f)\n", i, pDomIlluProfile->name, fSaturation, pCcmProfile1->saturation, pCcmProfile2->saturation); ret = SatInterpolateMatrices(fSaturation, pCcmProfile1, pCcmProfile2, undampedCcmMatrix); ret1 = SatInterpolateOffset(fSaturation, pCcmProfile1, pCcmProfile2, undampedCcOffset); if ((ret != XCAM_RETURN_NO_ERROR) && (ret1 != XCAM_RETURN_NO_ERROR)) { free(prob); return (ret); } } else if (ret == XCAM_RETURN_ERROR_OUTOFRANGE) { /* we don't need to interpolate */ LOGV_ACCM("No.%d Illu : %s, final fSaturation: %f (%f)\n", i, pDomIlluProfile->name, fSaturation, pCcmProfile1->saturation); memcpy(undampedCcmMatrix, pCcmProfile1->ccMatrix, sizeof(float)*9); memcpy(undampedCcOffset, pCcmProfile1->ccOffsets, sizeof(float)*3); } else { free(prob); return (ret); } probfSaturation = probfSaturation + fSaturation*prob[i]; for (int j = 0; j < 9; j++) hAccm->accmRest.undampedCcmMatrix[j] += undampedCcmMatrix[j]*prob[i]; for (int j = 0; j < 3; j++) hAccm->accmRest.undampedCcOffset[j] += undampedCcOffset[j]*prob[i]; } hAccm->accmRest.fSaturation = probfSaturation; hAccm->accmRest.pCcmProfile1 = pCcmProfile1; hAccm->accmRest.pCcmProfile2 = pCcmProfile2; // 3) free(prob); prob = NULL; } else { int dominateIlluProfileIdx; int dominateIlluListSize = 15;//to do from xml; float varianceLumaTh = 0.006;//to do from xml; ret = illuminant_index_estimation_ccm(pCcm->TuningPara.aCcmCof_len, pCcm->TuningPara.aCcmCof, hAccm->accmSwInfo.awbGain, &dominateIlluProfileIdx); RETURN_RESULT_IF_DIFFERENT(ret, XCAM_RETURN_NO_ERROR); UpdateDominateIlluList(&hAccm->accmRest.dominateIlluList, dominateIlluProfileIdx, dominateIlluListSize); StableIlluEstimation(hAccm->accmRest.dominateIlluList, dominateIlluListSize, pCcm->TuningPara.aCcmCof_len, hAccm->accmSwInfo.varianceLuma ,varianceLumaTh, hAccm->accmSwInfo.awbConverged, hAccm->accmRest.dominateIlluProfileIdx, &dominateIlluProfileIdx); hAccm->accmRest.dominateIlluProfileIdx = dominateIlluProfileIdx; // 2) pDomIlluProfile = &pCcm->TuningPara.aCcmCof[dominateIlluProfileIdx]; interpolation(pDomIlluProfile->gain_sat_curve.gains, pDomIlluProfile->gain_sat_curve.sat, 4, sensorGain, &fSaturation); hAccm->accmRest.fSaturation = fSaturation; //3) ret = SatSelectCcmProfiles( hAccm->accmRest.fSaturation, pDomIlluProfile->matrixUsed_len, hAccm->pCcmMatrixAll[dominateIlluProfileIdx], &pCcmProfile1, &pCcmProfile2); if (ret == XCAM_RETURN_NO_ERROR) { if (pCcmProfile1 && pCcmProfile2) LOGD_ACCM("final fSaturation: %f (%f .. %f)\n", hAccm->accmRest.fSaturation, pCcmProfile1->saturation, pCcmProfile2->saturation); ret = SatInterpolateMatrices( hAccm->accmRest.fSaturation, pCcmProfile1, pCcmProfile2, hAccm->accmRest.undampedCcmMatrix); if (ret != XCAM_RETURN_NO_ERROR) { return (ret); } ret = SatInterpolateOffset( hAccm->accmRest.fSaturation, pCcmProfile1, pCcmProfile2, hAccm->accmRest.undampedCcOffset); if (ret != XCAM_RETURN_NO_ERROR) { return (ret); } } else if (ret == XCAM_RETURN_ERROR_OUTOFRANGE) { /* we don't need to interpolate */ LOGD_ACCM("final fSaturation: %f (%f)\n", hAccm->accmRest.fSaturation, pCcmProfile1->saturation); memcpy(hAccm->accmRest.undampedCcmMatrix, pCcmProfile1->ccMatrix, sizeof(float)*9); memcpy(hAccm->accmRest.undampedCcOffset, pCcmProfile1->ccOffsets, sizeof(float)*3); } else { return (ret); } hAccm->accmRest.pCcmProfile1 = pCcmProfile1; hAccm->accmRest.pCcmProfile2 = pCcmProfile2; } //4) calc scale for y_alpha_curve float fScale = 1.0; #if 0 //real use interpolation(hAccm->calibCcm->luma_ccm.alpha_gain, hAccm->calibCcm->luma_ccm.alpha_scale, hAccm->calibCcm->luma_ccm.gain_scale_cure_size, sensorGain, &fScale); #else //for test, to be same with demo for( int i = 0; i < 9; i++) { int j = uint16_t(sensorGain); j = (j > (1 << 8)) ? (1 << 8) : j; if(j <= (1 << i)) { fScale = pCcm->lumaCCM.gain_alphaScale_curve.scale[i]; break; } } #endif // 5) color inhibition adjust for api float flevel2; interpolation(hAccm->mCurAtt.stAuto.color_inhibition.sensorGain, hAccm->mCurAtt.stAuto.color_inhibition.level, RK_AIQ_ACCM_COLOR_GAIN_NUM, sensorGain, &flevel2); hAccm->accmRest.color_inhibition_level = flevel2; for(int i = 0; i < RK_AIQ_ACCM_COLOR_GAIN_NUM; i++) { LOGV_ACCM(" color_inhibition sensorGain[%d]: %f, color_inhibition level[%d]: %f,", i, hAccm->mCurAtt.stAuto.color_inhibition.sensorGain[i], i, hAccm->mCurAtt.stAuto.color_inhibition.level[i]); } if(flevel2 > 100 || flevel2 < 0) { LOGE_ACCM("flevel2: %f is invalid ,should be in the range [0 100]\n", flevel2); ret = XCAM_RETURN_ERROR_PARAM; return(ret); } LOGD_ACCM("fScale: %f , color inhibition level:%f, ", fScale, flevel2); fScale *= (100 - flevel2) / 100; LOGD_ACCM("final fScale: %f \n", fScale); // 6) saturation adjust for api float flevel1; interpolation(hAccm->mCurAtt.stAuto.color_saturation.sensorGain, hAccm->mCurAtt.stAuto.color_saturation.level, RK_AIQ_ACCM_COLOR_GAIN_NUM, sensorGain, &flevel1); for(int i = 0; i < RK_AIQ_ACCM_COLOR_GAIN_NUM; i++) { LOGV_ACCM("color_saturation sensorGain[%d]: %f, color_saturation level[%d]: %f,", i, hAccm->mCurAtt.stAuto.color_saturation.sensorGain[i], i, hAccm->mCurAtt.stAuto.color_saturation.level[i]); } if(flevel1 > 100 || flevel1 < 0) { LOGE_ACCM("flevel1: %f is invalid ,should be in the range [0 100]\n", flevel1); ret = XCAM_RETURN_ERROR_PARAM; return(ret); } hAccm->accmRest.color_saturation_level = flevel1; LOGD_ACCM("fSaturation: %f , color saturation level:%f\n", fSaturation, flevel1); Saturationadjust( fScale, hAccm ); for(int i = 0; i < CCM_CURVE_DOT_NUM; i++) { //set to ic to do bit check hAccm->ccmHwConf.alp_y[i] = fScale * pCcm->lumaCCM.y_alpha_curve[i]; } } if (!hAccm->accmSwInfo.ccmConverged ||hAccm->update || hAccm->updateAtt) { // 7) . Damping ret = Damping((pCcm->TuningPara.damp_enable && hAccm->count > 1) ? hAccm->accmSwInfo.awbIIRDampCoef : 0, hAccm->accmRest.undampedCcmMatrix, hAccm->accmRest.dampedCcmMatrix, hAccm->accmRest.undampedCcOffset, hAccm->accmRest.dampedCcOffset); float d_ccm = 0; float d_ccoff = 0; for (int i = 0; i < 9; i++) d_ccm += fabs(hAccm->accmRest.undampedCcmMatrix[i] - hAccm->accmRest.dampedCcmMatrix[i]); for (int i = 0; i < 3; i++) d_ccoff += fabs(hAccm->accmRest.undampedCcOffset[i] - hAccm->accmRest.dampedCcOffset[i]); if ((d_ccm < DIVMIN)&&(d_ccoff < DIVMIN)) hAccm->accmSwInfo.ccmConverged = true; else hAccm->accmSwInfo.ccmConverged = false; } // 8) set to ic to do bit check memcpy(hAccm->ccmHwConf.matrix, hAccm->accmRest.dampedCcmMatrix, sizeof(hAccm->accmRest.dampedCcmMatrix)); memcpy(hAccm->ccmHwConf.offs, hAccm->accmRest.dampedCcOffset, sizeof(hAccm->accmRest.dampedCcOffset)); LOG1_ACCM("%s: (exit)\n", __FUNCTION__); return (ret); } XCamReturn AccmManualConfig ( accm_handle_t hAccm ) { LOG1_ACCM("%s: (enter)\n", __FUNCTION__); XCamReturn ret = XCAM_RETURN_NO_ERROR; memcpy(hAccm->ccmHwConf.matrix, hAccm->mCurAtt.stManual.matrix, sizeof(hAccm->mCurAtt.stManual.matrix)); memcpy(hAccm->ccmHwConf.offs, hAccm->mCurAtt.stManual.offs, sizeof(hAccm->mCurAtt.stManual.offs)); memcpy(hAccm->ccmHwConf.alp_y, hAccm->mCurAtt.stManual.alp_y, sizeof(hAccm->mCurAtt.stManual.alp_y)); hAccm->ccmHwConf.bound_bit = hAccm->mCurAtt.stManual.bound_bit; LOG1_ACCM("%s: (exit)\n", __FUNCTION__); return ret; } XCamReturn AccmConfig ( accm_handle_t hAccm ) { LOG1_ACCM("%s: (enter)\n", __FUNCTION__); XCamReturn ret = XCAM_RETURN_NO_ERROR; LOGD_ACCM("=========================================\n"); LOGD_ACCM("%s: updateAtt: %d\n", __FUNCTION__, hAccm->updateAtt); if(hAccm->updateAtt) { hAccm->mCurAtt.mode = hAccm->mNewAtt.mode; hAccm->mCurAtt.byPass = hAccm->mNewAtt.byPass; if (hAccm->mCurAtt.mode == RK_AIQ_CCM_MODE_TOOL) { hAccm->mCurAtt.byPass = !(hAccm->mNewAtt.stTool.control.enable); hAccm->mCurAtt.stTool = hAccm->mNewAtt.stTool; } else if (hAccm->mCurAtt.mode == RK_AIQ_CCM_MODE_AUTO) hAccm->mCurAtt.stAuto = hAccm->mNewAtt.stAuto; else hAccm->mCurAtt.stManual = hAccm->mNewAtt.stManual; } LOGD_ACCM("%s: CCM update: %d\n", __FUNCTION__, hAccm->update); LOGD_ACCM("%s: CCM Converged: %d\n", __FUNCTION__, hAccm->accmSwInfo.ccmConverged); if (hAccm->mCurAtt.mode == RK_AIQ_CCM_MODE_AUTO){ hAccm->mCurAtt.byPass = !(hAccm->calibV2Ccm->control.enable); } LOGD_ACCM("%s: byPass: %d mode:%d \n", __FUNCTION__, hAccm->mCurAtt.byPass, hAccm->mCurAtt.mode); if(hAccm->mCurAtt.byPass != true && hAccm->accmSwInfo.grayMode != true) { hAccm->ccmHwConf.ccmEnable = true; if((hAccm->mCurAtt.mode == RK_AIQ_CCM_MODE_AUTO)|| (hAccm->mCurAtt.mode == RK_AIQ_CCM_MODE_TOOL)){ if (hAccm->updateAtt || hAccm->update ||(!hAccm->accmSwInfo.ccmConverged)) AccmAutoConfig(hAccm); } else if(hAccm->mCurAtt.mode == RK_AIQ_CCM_MODE_MANUAL) { if (hAccm->updateAtt || hAccm->update) AccmManualConfig(hAccm); } else { LOGE_ACCM("%s: hAccm->mCurAtt.mode(%d) is invalid \n", __FUNCTION__, hAccm->mCurAtt.mode); } memcpy(hAccm->mCurAtt.stManual.matrix, hAccm->ccmHwConf.matrix, sizeof(hAccm->ccmHwConf.matrix)); memcpy(hAccm->mCurAtt.stManual.offs, hAccm->ccmHwConf.offs, sizeof(hAccm->ccmHwConf.offs)); memcpy(hAccm->mCurAtt.stManual.alp_y, hAccm->ccmHwConf.alp_y, sizeof(hAccm->ccmHwConf.alp_y)); } else { hAccm->ccmHwConf.ccmEnable = false; } LOGV_ACCM( " set to ic ccmEnable :%d bound_bit:%f\n", hAccm->ccmHwConf.ccmEnable, hAccm->ccmHwConf.bound_bit); LOGD_ACCM( " set to ic CcmMatrix: %f,%f,%f,%f,%f,%f,%f,%f,%f CcOffset:%f,%f,%f \n", hAccm->ccmHwConf.matrix[0], hAccm->ccmHwConf.matrix[1], hAccm->ccmHwConf.matrix[2], hAccm->ccmHwConf.matrix[3], hAccm->ccmHwConf.matrix[4], hAccm->ccmHwConf.matrix[5], hAccm->ccmHwConf.matrix[6], hAccm->ccmHwConf.matrix[7], hAccm->ccmHwConf.matrix[8], hAccm->ccmHwConf.offs[0], hAccm->ccmHwConf.offs[1], hAccm->ccmHwConf.offs[2] ); LOGV_ACCM( " set to ic rgb2y_para: %f,%f,%f\n", hAccm->ccmHwConf.rgb2y_para[0], hAccm->ccmHwConf.rgb2y_para[1], hAccm->ccmHwConf.rgb2y_para[2] ); LOGV_ACCM( " set to ic alp_y: %f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f \n", hAccm->ccmHwConf.alp_y[0], hAccm->ccmHwConf.alp_y[1], hAccm->ccmHwConf.alp_y[2], hAccm->ccmHwConf.alp_y[3], hAccm->ccmHwConf.alp_y[4], hAccm->ccmHwConf.alp_y[5], hAccm->ccmHwConf.alp_y[6], hAccm->ccmHwConf.alp_y[7], hAccm->ccmHwConf.alp_y[8], hAccm->ccmHwConf.alp_y[9], hAccm->ccmHwConf.alp_y[10], hAccm->ccmHwConf.alp_y[11], hAccm->ccmHwConf.alp_y[12], hAccm->ccmHwConf.alp_y[13], hAccm->ccmHwConf.alp_y[14], hAccm->ccmHwConf.alp_y[15], hAccm->ccmHwConf.alp_y[16] ); hAccm->count = ((hAccm->count + 2) > (65536)) ? 2 : (hAccm->count + 1); LOGD_ACCM( "===================================================== \n"); LOG1_ACCM("%s: (exit)\n", __FUNCTION__); return ret; } /************************************************** * ReloadCCMCalibV2 * config stTool used new CalibV2 json para ***************************************************/ static XCamReturn ReloadCCMCalibV2(accm_handle_t hAccm, const CalibDbV2_Ccm_Para_V2_t *calibv2_ccm) { CalibDbV2_Ccm_Para_V2_t *stCcm = &hAccm->mCurAtt.stTool; if (stCcm == NULL){ LOGE_ACCM("%s: CCM stTool is NULL !!!", __FUNCTION__); return XCAM_RETURN_ERROR_PARAM; } int clearillu = 0; if (calibv2_ccm->TuningPara.aCcmCof_len != stCcm->TuningPara.aCcmCof_len) clearillu = 1; else { int findillu = 0; for (int i = 0; i < stCcm->TuningPara.aCcmCof_len; i++){ for (int j = 0; j < stCcm->TuningPara.aCcmCof_len; j++){ if (strcmp(stCcm->TuningPara.aCcmCof[i].name, calibv2_ccm->TuningPara.aCcmCof[i].name) == 0){ findillu = 1; if (! (stCcm->TuningPara.aCcmCof[i].awbGain[0] == calibv2_ccm->TuningPara.aCcmCof[i].awbGain[0])&&( stCcm->TuningPara.aCcmCof[i].awbGain[1] == calibv2_ccm->TuningPara.aCcmCof[i].awbGain[1])){ clearillu = 1; LOGI_ACCM( "%s: awbGain in aCcmCof has been changed. \n", calibv2_ccm->TuningPara.aCcmCof[i].name); break; } } } if (findillu == 0) clearillu = 1; if (clearillu == 1) break; } } if (clearillu == 1) ClearList(&hAccm->accmRest.dominateIlluList); hAccm->mCurAtt.stTool = *calibv2_ccm; return (XCAM_RETURN_NO_ERROR); } /********************************** *Update CCM CalibV2 Para * Prepare init * Mode change: reinit * Res change: continue * Calib change: continue ***************************************/ static XCamReturn UpdateCcmCalibV2Para(accm_handle_t hAccm) { LOG1_ACCM("%s: (enter) \n", __FUNCTION__); XCamReturn ret = XCAM_RETURN_NO_ERROR; bool config_calib = !!(hAccm->accmSwInfo.prepare_type & RK_AIQ_ALGO_CONFTYPE_UPDATECALIB); const CalibDbV2_Ccm_Para_V2_t* calib_ccm = hAccm->calibV2Ccm; if (!config_calib) { return(ret); } hAccm->mCurAtt.mode = (rk_aiq_ccm_op_mode_t)calib_ccm->control.mode; ReloadCCMCalibV2(hAccm, calib_ccm); ret = pCcmMatrixAll_init(hAccm, &calib_ccm->TuningPara); hAccm->mCurAtt.byPass = !(calib_ccm->control.enable); hAccm->ccmHwConf.bound_bit = calib_ccm->lumaCCM.low_bound_pos_bit; memcpy( hAccm->ccmHwConf.rgb2y_para, calib_ccm->lumaCCM.rgb2y_para, sizeof(calib_ccm->lumaCCM.rgb2y_para)); memcpy( hAccm->ccmHwConf.alp_y, calib_ccm->lumaCCM.y_alpha_curve, sizeof(hAccm->ccmHwConf.alp_y)); // config manual ccm memcpy(hAccm->mCurAtt.stManual.matrix, calib_ccm->manualPara.ccMatrix, sizeof(calib_ccm->manualPara.ccMatrix)); memcpy(hAccm->mCurAtt.stManual.offs, calib_ccm->manualPara.ccOffsets, sizeof(calib_ccm->manualPara.ccOffsets)); memcpy(hAccm->mCurAtt.stManual.alp_y, hAccm->ccmHwConf.alp_y, sizeof( hAccm->ccmHwConf.alp_y)); hAccm->mCurAtt.stManual.bound_bit = hAccm->ccmHwConf.bound_bit; hAccm->accmSwInfo.ccmConverged = false; hAccm->calib_update = true; #if 0 //awbGain get from awb module ret = Swinfo_wbgain_init(hAccm->accmSwInfo.awbGain, &hAccm->mCurAtt.stTool.mode_cell[currentHdrNormalMode], hAccm->lsForFirstFrame); #endif ClearList(&hAccm->accmRest.problist); LOG1_ACCM("%s: (exit)\n", __FUNCTION__); return(ret); } XCamReturn AccmInit(accm_handle_t *hAccm, const CamCalibDbV2Context_t* calibv2) { LOGI_ACCM("%s: (enter)\n", __FUNCTION__); XCamReturn ret = XCAM_RETURN_NO_ERROR; *hAccm = (accm_context_t*)malloc(sizeof(accm_context_t)); accm_context_t* accm_context = *hAccm; memset(accm_context, 0, sizeof(accm_context_t)); if(calibv2 == NULL) { return XCAM_RETURN_ERROR_PARAM; } const CalibDbV2_Ccm_Para_V2_t *calib_ccm = (CalibDbV2_Ccm_Para_V2_t*)(CALIBDBV2_GET_MODULE_PTR((void*)calibv2, ccm_calib)); if (calib_ccm == NULL) return XCAM_RETURN_ERROR_MEM; accm_context->accmSwInfo.sensorGain = 1.0; accm_context->accmSwInfo.awbIIRDampCoef = 0; accm_context->accmSwInfo.varianceLuma = 255; accm_context->accmSwInfo.awbConverged = false; accm_context->accmSwInfo.awbGain[0] = 1; accm_context->accmSwInfo.awbGain[1] = 1; accm_context->count = 0; accm_context->accmSwInfo.prepare_type = RK_AIQ_ALGO_CONFTYPE_UPDATECALIB | RK_AIQ_ALGO_CONFTYPE_NEEDRESET; // todo whm --- CalibDbV2_Ccm_Para_V2 accm_context->calibV2Ccm = calib_ccm; ret = UpdateCcmCalibV2Para(accm_context); for(int i = 0; i < RK_AIQ_ACCM_COLOR_GAIN_NUM; i++) { accm_context->mCurAtt.stAuto.color_inhibition.sensorGain[i] = 1; accm_context->mCurAtt.stAuto.color_inhibition.level[i] = 0; accm_context->mCurAtt.stAuto.color_saturation.sensorGain[i] = 1; accm_context->mCurAtt.stAuto.color_saturation.level[i] = 50; } accm_context->accmRest.color_inhibition_level = 0; accm_context->accmRest.color_saturation_level = 100; LOGI_ACCM("%s: (exit)\n", __FUNCTION__); return(ret); } XCamReturn AccmRelease(accm_handle_t hAccm) { LOGI_ACCM("%s: (enter)\n", __FUNCTION__); XCamReturn ret = XCAM_RETURN_NO_ERROR; ClearList(&hAccm->accmRest.dominateIlluList); ClearList(&hAccm->accmRest.problist); free(hAccm); hAccm = NULL; LOGI_ACCM("%s: (exit)\n", __FUNCTION__); return(ret); } // todo whm XCamReturn AccmPrepare(accm_handle_t hAccm) { LOGI_ACCM("%s: (enter)\n", __FUNCTION__); XCamReturn ret = XCAM_RETURN_NO_ERROR; ret = UpdateCcmCalibV2Para(hAccm); RETURN_RESULT_IF_DIFFERENT(ret, XCAM_RETURN_NO_ERROR); LOGI_ACCM("%s: (exit)\n", __FUNCTION__); return ret; } XCamReturn AccmPreProc(accm_handle_t hAccm) { LOG1_ACCM("%s: (enter)\n", __FUNCTION__); XCamReturn ret = XCAM_RETURN_NO_ERROR; LOG1_ACCM("%s: (exit)\n", __FUNCTION__); return(ret); } XCamReturn AccmProcessing(accm_handle_t hAccm) { LOG1_ACCM("%s: (enter)\n", __FUNCTION__); XCamReturn ret = XCAM_RETURN_NO_ERROR; LOG1_ACCM("%s: (exit)\n", __FUNCTION__); return(ret); } RKAIQ_END_DECLARE