/* * rk_aiq_alsc_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 "alsc/rk_aiq_alsc_algo.h" #include "xcam_log.h" #include "interpolation.h" RKAIQ_BEGIN_DECLARE static XCamReturn illuminant_index_estimation(int light_num, const CalibDb_AlscCof_ill_t illAll[], float awbGain[2], int* illuminant_index) { LOG1_ALSC( "%s: (enter)\n", __FUNCTION__); float minDist = 9999999; float dist[8]; float nRG, nBG; *illuminant_index = 0; XCamReturn ret = XCAM_RETURN_ERROR_FAILED; for(int i = 0; i < light_num; i++) { nRG = awbGain[0]; nBG = awbGain[1]; 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_ALSC("fail to estimate illuminant!!!\n"); } LOGD_ALSC( "wbGain:%f,%f, estimation illuminant is %s(%d) \n", awbGain[0], awbGain[1], illAll[*illuminant_index].illuName, *illuminant_index); LOG1_ALSC( "%s: (exit)\n", __FUNCTION__); return ret; } static XCamReturn AwbOrderLscProfilesByVignetting ( const CalibDb_LscTableProfile_t* pLscProfiles[], const int32_t cnt ) { int32_t i, j; for (i = 0; i < (cnt - 1); ++i) { for (j = 0; j < (cnt - i - 1); ++j) { if (pLscProfiles[j]->vignetting < pLscProfiles[j + 1]->vignetting) { const CalibDb_LscTableProfile_t* temp = pLscProfiles[j]; pLscProfiles[j] = pLscProfiles[j + 1]; pLscProfiles[j + 1] = temp; } } } return (XCAM_RETURN_NO_ERROR); } static XCamReturn VignSelectLscProfiles ( const float fVignetting, int32_t no_lsc, const CalibDb_LscTableProfile_t* pLscProfiles[], const CalibDb_LscTableProfile_t** pLscProfile1, const CalibDb_LscTableProfile_t** pLscProfile2 ) { XCamReturn XCamReturn = XCAM_RETURN_NO_ERROR; if ((no_lsc == 0) || (pLscProfiles == NULL) || (pLscProfile1 == NULL) || (pLscProfile2 == NULL)) { return (XCAM_RETURN_ERROR_PARAM); } if (fVignetting >= pLscProfiles[0]->vignetting) { *pLscProfile1 = pLscProfiles[0]; *pLscProfile2 = NULL; LOGD_ALSC( "select:%s \n", (*pLscProfile1)->name); XCamReturn = XCAM_RETURN_ERROR_OUTOFRANGE; } else { int32_t nLast = no_lsc - 1; if (fVignetting <= pLscProfiles[nLast]->vignetting) { *pLscProfile1 = pLscProfiles[nLast]; *pLscProfile2 = NULL; LOGD_ALSC( "select:%s \n", (*pLscProfile1)->name); XCamReturn = XCAM_RETURN_ERROR_OUTOFRANGE; } else { uint16_t n = 0; /* find the segment */ while ((fVignetting <= pLscProfiles[n]->vignetting) && (n <= nLast)) { n++; } if (n > 0) n--; *pLscProfile1 = pLscProfiles[n]; *pLscProfile2 = pLscProfiles[n + 1]; } } return (XCamReturn); } /****************************************************************************** * InterpolateMatrices *****************************************************************************/ static XCamReturn VignInterpolateMatrices ( const float fVignetting, const CalibDb_LscTableProfile_t* pLscProfile1, const CalibDb_LscTableProfile_t* pLscProfile2, CamLscMatrix_t* pResMatrix ) { XCamReturn iXCamReturn = XCAM_RETURN_ERROR_PARAM; if ((pLscProfile1 != NULL) && (pLscProfile2 != NULL) && (pResMatrix != NULL)) { float fVigA = pLscProfile1->vignetting; float fVigB = pLscProfile2->vignetting; float f1 = (fVigB - fVignetting) / (fVigB - fVigA); /* FLOAT f2 = ( fVigB - fVignetting ) / ( fVigB - fVigA ); */ float f2 = 1.0f - f1; LOGD_ALSC( "select:%s :%f and %s :%f", pLscProfile1->name, f1, pLscProfile2->name, f2); /* left shift 16 */ uint32_t f1_ = (uint32_t)(f1 * 65536.0f); uint32_t f2_ = (uint32_t)(f2 * 65536.0f); int16_t i; uint32_t red; uint32_t greenr; uint32_t greenb; uint32_t blue; for (i = 0; i < (17 * 17); i++) { red = (f1_ * (uint32_t)pLscProfile1->LscMatrix[CAM_4CH_COLOR_COMPONENT_RED].uCoeff[i]) + (f2_ * (uint32_t)pLscProfile2->LscMatrix[CAM_4CH_COLOR_COMPONENT_RED].uCoeff[i]); greenr = (f1_ * (uint32_t)pLscProfile1->LscMatrix[CAM_4CH_COLOR_COMPONENT_GREENR].uCoeff[i]) + (f2_ * (uint32_t)pLscProfile2->LscMatrix[CAM_4CH_COLOR_COMPONENT_GREENR].uCoeff[i]); greenb = (f1_ * (uint32_t)pLscProfile1->LscMatrix[CAM_4CH_COLOR_COMPONENT_GREENB].uCoeff[i]) + (f2_ * (uint32_t)pLscProfile2->LscMatrix[CAM_4CH_COLOR_COMPONENT_GREENB].uCoeff[i]); blue = (f1_ * (uint32_t)pLscProfile1->LscMatrix[CAM_4CH_COLOR_COMPONENT_BLUE].uCoeff[i]) + (f2_ * (uint32_t)pLscProfile2->LscMatrix[CAM_4CH_COLOR_COMPONENT_BLUE].uCoeff[i]); /* with round up (add 65536/2 <=> 0.5) before right shift */ pResMatrix->LscMatrix[CAM_4CH_COLOR_COMPONENT_RED].uCoeff[i] = (uint16_t)((red + (65536 >> 1)) >> 16); pResMatrix->LscMatrix[CAM_4CH_COLOR_COMPONENT_GREENR].uCoeff[i] = (uint16_t)((greenr + (65536 >> 1)) >> 16); pResMatrix->LscMatrix[CAM_4CH_COLOR_COMPONENT_GREENB].uCoeff[i] = (uint16_t)((greenb + (65536 >> 1)) >> 16); pResMatrix->LscMatrix[CAM_4CH_COLOR_COMPONENT_BLUE].uCoeff[i] = (uint16_t)((blue + (65536 >> 1)) >> 16); } iXCamReturn = XCAM_RETURN_NO_ERROR; } return (iXCamReturn); } /****************************************************************************** * Damping *****************************************************************************/ static XCamReturn Damping ( const float damp, /**< damping coefficient */ CamLscMatrix_t* pMatrixUndamped, /**< undamped new computed matrices */ CamLscMatrix_t* pMatrixDamped /**< old matrices and XCamReturn */ ) { XCamReturn XCamReturn = XCAM_RETURN_ERROR_PARAM; if ((pMatrixUndamped != NULL) && (pMatrixDamped != NULL)) { /* left shift 16 */ uint32_t f1_ = (uint32_t)(damp * 65536.0f); uint32_t f2_ = (uint32_t)(65536U - f1_); int16_t i; uint32_t red; uint32_t greenr; uint32_t greenb; uint32_t blue; for (i = 0; i < (17 * 17); i++) { red = (f1_ * (uint32_t)pMatrixDamped->LscMatrix[CAM_4CH_COLOR_COMPONENT_RED].uCoeff[i]) + (f2_ * (uint32_t)pMatrixUndamped->LscMatrix[CAM_4CH_COLOR_COMPONENT_RED].uCoeff[i]); greenr = (f1_ * (uint32_t)pMatrixDamped->LscMatrix[CAM_4CH_COLOR_COMPONENT_GREENR].uCoeff[i]) + (f2_ * (uint32_t)pMatrixUndamped->LscMatrix[CAM_4CH_COLOR_COMPONENT_GREENR].uCoeff[i]); greenb = (f1_ * (uint32_t)pMatrixDamped->LscMatrix[CAM_4CH_COLOR_COMPONENT_GREENB].uCoeff[i]) + (f2_ * (uint32_t)pMatrixUndamped->LscMatrix[CAM_4CH_COLOR_COMPONENT_GREENB].uCoeff[i]); blue = (f1_ * (uint32_t)pMatrixDamped->LscMatrix[CAM_4CH_COLOR_COMPONENT_BLUE].uCoeff[i]) + (f2_ * (uint32_t)pMatrixUndamped->LscMatrix[CAM_4CH_COLOR_COMPONENT_BLUE].uCoeff[i]); /* with round up (add 65536/2 <=> 0.5) before right shift */ pMatrixDamped->LscMatrix[CAM_4CH_COLOR_COMPONENT_RED].uCoeff[i] = (uint16_t)((red + (65536 >> 1)) >> 16); pMatrixDamped->LscMatrix[CAM_4CH_COLOR_COMPONENT_GREENR].uCoeff[i] = (uint16_t)((greenr + (65536 >> 1)) >> 16); pMatrixDamped->LscMatrix[CAM_4CH_COLOR_COMPONENT_GREENB].uCoeff[i] = (uint16_t)((greenb + (65536 >> 1)) >> 16); pMatrixDamped->LscMatrix[CAM_4CH_COLOR_COMPONENT_BLUE].uCoeff[i] = (uint16_t)((blue + (65536 >> 1)) >> 16); } LOGD_ALSC( "dampfactor:%f", damp); LOGD_ALSC( " undampedLscMatrix r[0:3]:%d,%d,%d,%d, gr[0:3]:%d,%d,%d,%d, gb[0:3]:%d,%d,%d,%d, b[0:3]:%d,%d,%d,%d\n", pMatrixUndamped->LscMatrix[CAM_4CH_COLOR_COMPONENT_RED].uCoeff[0], pMatrixUndamped->LscMatrix[CAM_4CH_COLOR_COMPONENT_RED].uCoeff[1], pMatrixUndamped->LscMatrix[CAM_4CH_COLOR_COMPONENT_RED].uCoeff[2], pMatrixUndamped->LscMatrix[CAM_4CH_COLOR_COMPONENT_RED].uCoeff[3], pMatrixUndamped->LscMatrix[CAM_4CH_COLOR_COMPONENT_GREENR].uCoeff[0], pMatrixUndamped->LscMatrix[CAM_4CH_COLOR_COMPONENT_GREENR].uCoeff[1], pMatrixUndamped->LscMatrix[CAM_4CH_COLOR_COMPONENT_GREENR].uCoeff[2], pMatrixUndamped->LscMatrix[CAM_4CH_COLOR_COMPONENT_GREENR].uCoeff[3], pMatrixUndamped->LscMatrix[CAM_4CH_COLOR_COMPONENT_GREENB].uCoeff[0], pMatrixUndamped->LscMatrix[CAM_4CH_COLOR_COMPONENT_GREENB].uCoeff[1], pMatrixUndamped->LscMatrix[CAM_4CH_COLOR_COMPONENT_GREENB].uCoeff[2], pMatrixUndamped->LscMatrix[CAM_4CH_COLOR_COMPONENT_GREENB].uCoeff[3], pMatrixUndamped->LscMatrix[CAM_4CH_COLOR_COMPONENT_BLUE].uCoeff[0], pMatrixUndamped->LscMatrix[CAM_4CH_COLOR_COMPONENT_BLUE].uCoeff[1], pMatrixUndamped->LscMatrix[CAM_4CH_COLOR_COMPONENT_BLUE].uCoeff[2], pMatrixUndamped->LscMatrix[CAM_4CH_COLOR_COMPONENT_BLUE].uCoeff[3] ); LOGD_ALSC( " dampedLscMatrix r[0:3]:%d,%d,%d,%d, gr[0:3]:%d,%d,%d,%d, gb[0:3]:%d,%d,%d,%d, b[0:3]:%d,%d,%d,%d\n", pMatrixDamped->LscMatrix[CAM_4CH_COLOR_COMPONENT_RED].uCoeff[0], pMatrixDamped->LscMatrix[CAM_4CH_COLOR_COMPONENT_RED].uCoeff[1], pMatrixDamped->LscMatrix[CAM_4CH_COLOR_COMPONENT_RED].uCoeff[2], pMatrixDamped->LscMatrix[CAM_4CH_COLOR_COMPONENT_RED].uCoeff[3], pMatrixDamped->LscMatrix[CAM_4CH_COLOR_COMPONENT_GREENR].uCoeff[0], pMatrixDamped->LscMatrix[CAM_4CH_COLOR_COMPONENT_GREENR].uCoeff[1], pMatrixDamped->LscMatrix[CAM_4CH_COLOR_COMPONENT_GREENR].uCoeff[2], pMatrixDamped->LscMatrix[CAM_4CH_COLOR_COMPONENT_GREENR].uCoeff[3], pMatrixDamped->LscMatrix[CAM_4CH_COLOR_COMPONENT_GREENB].uCoeff[0], pMatrixDamped->LscMatrix[CAM_4CH_COLOR_COMPONENT_GREENB].uCoeff[1], pMatrixDamped->LscMatrix[CAM_4CH_COLOR_COMPONENT_GREENB].uCoeff[2], pMatrixDamped->LscMatrix[CAM_4CH_COLOR_COMPONENT_GREENB].uCoeff[3], pMatrixDamped->LscMatrix[CAM_4CH_COLOR_COMPONENT_BLUE].uCoeff[0], pMatrixDamped->LscMatrix[CAM_4CH_COLOR_COMPONENT_BLUE].uCoeff[1], pMatrixDamped->LscMatrix[CAM_4CH_COLOR_COMPONENT_BLUE].uCoeff[2], pMatrixDamped->LscMatrix[CAM_4CH_COLOR_COMPONENT_BLUE].uCoeff[3] ); XCamReturn = XCAM_RETURN_NO_ERROR; } return (XCamReturn); } static XCamReturn CamCalibDbGetLscProfileByName(const CalibDb_Lsc_t *calibLsc, char* name, const CalibDb_LscTableProfile_t **pLscTableProfile) { LOG1_ALSC("%s: (enter)\n", __FUNCTION__); XCamReturn ret = XCAM_RETURN_ERROR_FAILED; for(int i = 0; i < calibLsc->tableAllNum; i++) { //todo if(strcmp(calibLsc->tableAll[i].name, name) == 0) { *pLscTableProfile = &calibLsc->tableAll[i]; ret = XCAM_RETURN_NO_ERROR; break; } } if(ret != XCAM_RETURN_NO_ERROR) { LOGD_ALSC("can't find %s in tableAll\n", name); } LOG1_ALSC("%s: (exit)\n", __FUNCTION__); return ret; } static XCamReturn CamCalibDbGetLscResIdxByName(const CalibDb_Lsc_t *calibLsc, char* name, int *resIdx) { LOG1_ALSC("%s: (enter)\n", __FUNCTION__); XCamReturn ret = XCAM_RETURN_ERROR_FAILED; for(int i = 0; i < calibLsc->aLscCof.lscResNum; i++) { if(strcmp(calibLsc->aLscCof.lscResName[i], name) == 0) { *resIdx = i; ret = XCAM_RETURN_NO_ERROR; break; } } if(ret != XCAM_RETURN_NO_ERROR) { LOGE_ALSC("can't find %s in lscResName\n", name); } LOG1_ALSC("%s: (exit)\n", __FUNCTION__); return ret; } void UpdateDominateIlluList(List *l, int illu, int listMaxSize) { illu_node_t *pCurNode; illu_node_t *pDelNode; int sizeList; if(listMaxSize == 0) { return; } pCurNode = (illu_node_t*)malloc(sizeof(illu_node_t)); pCurNode->value = illu; ListPrepareItem(pCurNode); ListAddTail(l, pCurNode); sizeList = ListNoItems(l); if (sizeList > listMaxSize) { pDelNode = (illu_node_t *)ListRemoveHead(l); free(pDelNode); } } 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_ALSC("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 count2 = 0; int max_count = 0; for(int i=0; i max_count){ max_count = illuSet[i]; *newIllu = i; } } free(illuSet); LOGD_ALSC("varianceLuma %f, varianceLumaTh %f final estmination illu is %d\n", varianceLuma,varianceLumaTh,*newIllu ); } XCamReturn AlscAutoConfig ( alsc_handle_t hAlsc ) { LOG1_ALSC("%s: (enter) count:%d\n", __FUNCTION__, hAlsc->count); int caseIndex = hAlsc->alscRest.caseIndex; XCamReturn ret = XCAM_RETURN_NO_ERROR; const CalibDb_AlscCof_ill_t* pDomIlluProfile = NULL; const CalibDb_LscTableProfile_t* pLscProfile1 = NULL; const CalibDb_LscTableProfile_t* pLscProfile2 = NULL; if (hAlsc == NULL) { return XCAM_RETURN_ERROR_PARAM; } int dominateIlluProfileIdx; int resIdx; //1) int dominateIlluListSize = 15;//to do from xml; float varianceLumaTh = 0.006;//to do from xml; ret = illuminant_index_estimation(hAlsc->calibLsc->aLscCof.illuNum[caseIndex], hAlsc->calibLsc->aLscCof.illAll[caseIndex], hAlsc->alscSwInfo.awbGain, &dominateIlluProfileIdx); RETURN_RESULT_IF_DIFFERENT(ret, XCAM_RETURN_NO_ERROR); UpdateDominateIlluList(&hAlsc->alscRest.dominateIlluList, dominateIlluProfileIdx, dominateIlluListSize); StableIlluEstimation(hAlsc->alscRest.dominateIlluList, dominateIlluListSize, hAlsc->calibLsc->aLscCof.illuNum[caseIndex], hAlsc->alscSwInfo.varianceLuma ,varianceLumaTh, hAlsc->alscSwInfo.awbConverged, hAlsc->alscRest.dominateIlluProfileIdx, &dominateIlluProfileIdx); hAlsc->alscRest.dominateIlluProfileIdx = dominateIlluProfileIdx; // 2) cal resIdx ret = CamCalibDbGetLscResIdxByName( hAlsc->calibLsc, hAlsc->curResName, &resIdx ); RETURN_RESULT_IF_DIFFERENT(ret, XCAM_RETURN_NO_ERROR); hAlsc->alscRest.resIdx = resIdx; // 3) float sensorGain = hAlsc->alscSwInfo.sensorGain; float fVignetting; pDomIlluProfile = &hAlsc->calibLsc->aLscCof.illAll[caseIndex][dominateIlluProfileIdx]; interpolation(pDomIlluProfile->vignettingCurve.pSensorGain, pDomIlluProfile->vignettingCurve.pVignetting, pDomIlluProfile->vignettingCurve.arraySize, sensorGain, &fVignetting); hAlsc->alscRest.fVignetting = fVignetting; //4) // CalibDb_LscTableProfile_t* pLscProfiles = hAlsc->pLscTableAll[resIdx][dominateIlluProfileIdx]; ret = VignSelectLscProfiles(fVignetting, pDomIlluProfile->tableUsedNO, hAlsc->pLscTableAll[caseIndex][resIdx][dominateIlluProfileIdx], &pLscProfile1, &pLscProfile2); if (ret == XCAM_RETURN_NO_ERROR) { if (pLscProfile1 && pLscProfile2) LOGD_ALSC("fVignetting: %f (%f .. %f)\n", fVignetting, pLscProfile1->vignetting, pLscProfile2->vignetting); ret = VignInterpolateMatrices(fVignetting, pLscProfile1, pLscProfile2, &hAlsc->alscRest.undampedLscMatrixTable); if (ret != XCAM_RETURN_NO_ERROR) { return (ret); } } else if (ret == XCAM_RETURN_ERROR_OUTOFRANGE) { /* we don't need to interpolate */ LOGD_ALSC("fVignetting: %f (%f)\n", fVignetting, pLscProfile1->vignetting); memcpy(&hAlsc->alscRest.undampedLscMatrixTable, &pLscProfile1->LscMatrix[0], sizeof(CamLscMatrix_t)); } else { return (ret); } // 5) . Damping ret = Damping((hAlsc->calibLsc->damp_enable && hAlsc->count > 1) ? hAlsc->alscSwInfo.awbIIRDampCoef : 0, &hAlsc->alscRest.undampedLscMatrixTable, &hAlsc->alscRest.dampedLscMatrixTable); hAlsc->alscRest.pLscProfile1 = pLscProfile1; hAlsc->alscRest.pLscProfile2 = pLscProfile2; // 6 set to ic memcpy(hAlsc->lscHwConf.r_data_tbl, &hAlsc->alscRest.dampedLscMatrixTable.LscMatrix[CAM_4CH_COLOR_COMPONENT_RED].uCoeff, sizeof(hAlsc->alscRest.dampedLscMatrixTable.LscMatrix[CAM_4CH_COLOR_COMPONENT_RED].uCoeff)); memcpy(hAlsc->lscHwConf.gr_data_tbl, &hAlsc->alscRest.dampedLscMatrixTable.LscMatrix[CAM_4CH_COLOR_COMPONENT_GREENR].uCoeff, sizeof(hAlsc->alscRest.dampedLscMatrixTable.LscMatrix[CAM_4CH_COLOR_COMPONENT_GREENR].uCoeff)); memcpy(hAlsc->lscHwConf.gb_data_tbl, &hAlsc->alscRest.dampedLscMatrixTable.LscMatrix[CAM_4CH_COLOR_COMPONENT_GREENB].uCoeff, sizeof(hAlsc->alscRest.dampedLscMatrixTable.LscMatrix[CAM_4CH_COLOR_COMPONENT_GREENB].uCoeff)); memcpy(hAlsc->lscHwConf.b_data_tbl, &hAlsc->alscRest.dampedLscMatrixTable.LscMatrix[CAM_4CH_COLOR_COMPONENT_BLUE].uCoeff, sizeof(hAlsc->alscRest.dampedLscMatrixTable.LscMatrix[CAM_4CH_COLOR_COMPONENT_BLUE].uCoeff)); LOG1_ALSC("%s: (exit)\n", __FUNCTION__); return (ret); } XCamReturn AlscManualConfig ( alsc_handle_t hAlsc ) { LOG1_ALSC("%s: (enter)\n", __FUNCTION__); XCamReturn ret = XCAM_RETURN_NO_ERROR; memcpy(hAlsc->lscHwConf.r_data_tbl, hAlsc->mCurAtt.stManual.r_data_tbl, sizeof(hAlsc->mCurAtt.stManual.r_data_tbl)); memcpy(hAlsc->lscHwConf.gr_data_tbl, hAlsc->mCurAtt.stManual.gr_data_tbl, sizeof(hAlsc->mCurAtt.stManual.gr_data_tbl)); memcpy(hAlsc->lscHwConf.gb_data_tbl, hAlsc->mCurAtt.stManual.gb_data_tbl, sizeof(hAlsc->mCurAtt.stManual.gb_data_tbl)); memcpy(hAlsc->lscHwConf.b_data_tbl, hAlsc->mCurAtt.stManual.b_data_tbl, sizeof(hAlsc->mCurAtt.stManual.b_data_tbl)); LOG1_ALSC("%s: (exit)\n", __FUNCTION__); return ret; } XCamReturn AlscConfig ( alsc_handle_t hAlsc ) { LOG1_ALSC("%s: (enter)\n", __FUNCTION__); XCamReturn ret = XCAM_RETURN_NO_ERROR; LOGD_ALSC("%s: updateAtt: %d\n", __FUNCTION__, hAlsc->updateAtt); hAlsc->alscRest.caseIndex = USED_FOR_CASE_NORMAL; if((hAlsc->alscSwInfo.grayMode == true && hAlsc->alscRest.caseIndex != USED_FOR_CASE_GRAY)|| (hAlsc->alscSwInfo.grayMode == false && hAlsc->alscRest.caseIndex == USED_FOR_CASE_GRAY)){ ClearList(&hAlsc->alscRest.dominateIlluList); } if(hAlsc->alscSwInfo.grayMode){ hAlsc->alscRest.caseIndex = USED_FOR_CASE_GRAY; } if(hAlsc->updateAtt) { hAlsc->mCurAtt = hAlsc->mNewAtt; } LOGD_ALSC("%s: byPass: %d mode:%d used for case: %d\n", __FUNCTION__, hAlsc->mCurAtt.byPass, hAlsc->mCurAtt.mode,hAlsc->alscRest.caseIndex); if(hAlsc->mCurAtt.byPass != true ) { hAlsc->lscHwConf.lsc_en = true; if(hAlsc->mCurAtt.mode == RK_AIQ_LSC_MODE_AUTO) { AlscAutoConfig(hAlsc); } else if(hAlsc->mCurAtt.mode == RK_AIQ_LSC_MODE_MANUAL) { AlscManualConfig(hAlsc); } else { LOGE_ALSC("%s: hAlsc->mCurAtt.mode(%d) is invalid \n", __FUNCTION__, hAlsc->mCurAtt.mode); } memcpy(hAlsc->mCurAtt.stManual.r_data_tbl, hAlsc->lscHwConf.r_data_tbl, sizeof(hAlsc->mCurAtt.stManual.r_data_tbl)); memcpy(hAlsc->mCurAtt.stManual.gr_data_tbl, hAlsc->lscHwConf.gr_data_tbl, sizeof(hAlsc->mCurAtt.stManual.gr_data_tbl)); memcpy(hAlsc->mCurAtt.stManual.gb_data_tbl, hAlsc->lscHwConf.gb_data_tbl, sizeof(hAlsc->mCurAtt.stManual.gb_data_tbl)); memcpy(hAlsc->mCurAtt.stManual.b_data_tbl, hAlsc->lscHwConf.b_data_tbl, sizeof(hAlsc->mCurAtt.stManual.b_data_tbl)); } else { hAlsc->lscHwConf.lsc_en = false; } hAlsc->count = ((hAlsc->count + 2) > (65536)) ? 2 : (hAlsc->count + 1); LOGD_ALSC( "set to ic LscMatrix r[0:3]:%d,%d,%d,%d, gr[0:3]:%d,%d,%d,%d, gb[0:3]:%d,%d,%d,%d, b[0:3]:%d,%d,%d,%d\n", hAlsc->lscHwConf.r_data_tbl[0], hAlsc->lscHwConf.r_data_tbl[1], hAlsc->lscHwConf.r_data_tbl[2], hAlsc->lscHwConf.r_data_tbl[3], hAlsc->lscHwConf.gr_data_tbl[0], hAlsc->lscHwConf.gr_data_tbl[1], hAlsc->lscHwConf.gr_data_tbl[2], hAlsc->lscHwConf.gr_data_tbl[3], hAlsc->lscHwConf.gb_data_tbl[0], hAlsc->lscHwConf.gb_data_tbl[1], hAlsc->lscHwConf.gb_data_tbl[2], hAlsc->lscHwConf.gb_data_tbl[3], hAlsc->lscHwConf.b_data_tbl[0], hAlsc->lscHwConf.b_data_tbl[1], hAlsc->lscHwConf.b_data_tbl[2], hAlsc->lscHwConf.b_data_tbl[3] ); LOG1_ALSC("%s: (exit)\n", __FUNCTION__); return ret; } static XCamReturn UpdateLscCalibPara(alsc_handle_t hAlsc) { LOGI_ALSC("%s: (enter) \n", __FUNCTION__); XCamReturn ret = XCAM_RETURN_NO_ERROR; bool config_calib = !!(hAlsc->alscSwInfo.prepare_type & RK_AIQ_ALGO_CONFTYPE_UPDATECALIB); if(!config_calib) { return(ret); } const CalibDb_Lsc_t* calib_lsc = hAlsc->calibLsc; #if 0 //awbGain get from awb module bool lsFound; for(int i = 0; i < calib_lsc->aLscCof.illuNum[caseIndex]; i++) { if(strcmp(calib_lsc->aLscCof.illAll[caseIndex][i].illuName, calib->awb.strategy_cfg.lsForFirstFrame) == 0) { memcpy(hAlsc->alscSwInfo.awbGain, calib_lsc->aLscCof.illAll[caseIndex][i].awbGain, sizeof(hAlsc->alscSwInfo.awbGain)); lsFound = true; LOGD_ALSC("%s: alsc lsForFirstFrame:%s", __FUNCTION__, calib_lsc->aLscCof.illAll[caseIndex][i].illuName); break; } } if(calib_lsc->aLscCof.illuNum[caseIndex] > 0 && lsFound == false) { memcpy(hAlsc->alscSwInfo.awbGain, calib_lsc->aLscCof.illAll[caseIndex][0].awbGain, sizeof(hAlsc->alscSwInfo.awbGain)); LOGD_ALSC("%s: alsc lsForFirstFrame:%s", __FUNCTION__, calib_lsc->aLscCof.illAll[caseIndex][0].illuName); } #endif LOGI_ALSC("%s: alsc illunum:%d", __FUNCTION__, calib_lsc->aLscCof.illuNum[hAlsc->alscRest.caseIndex]); // 1) malloc get and reorder para pLscTableProfileVig_t pLscTableProfileVig; pLscTableProfileVigIll_t pLscTableProfileVigIll; pLscTableProfileVigIllRes_t pLscTableProfileVigIllRes; hAlsc->pLscTableAll = (pLscTableProfileVigIllResUC_t)malloc(sizeof(pLscTableProfileVigIllRes_t) * USED_FOR_CASE_MAX); memset(hAlsc->pLscTableAll, 0, sizeof(pLscTableProfileVigIllRes_t) * USED_FOR_CASE_MAX); for(int c=0;caLscCof.lscResNum); memset(pLscTableProfileVigIllRes,0, sizeof(pLscTableProfileVigIll_t)*calib_lsc->aLscCof.lscResNum); hAlsc->pLscTableAll[c] = pLscTableProfileVigIllRes; for (int k = 0; k < calib_lsc->aLscCof.lscResNum; k++) { pLscTableProfileVigIll = (pLscTableProfileVigIll_t)malloc(sizeof(pLscTableProfileVig_t)*calib_lsc->aLscCof.illuNum[c]); memset(pLscTableProfileVigIll, 0, sizeof(pLscTableProfileVig_t)*calib_lsc->aLscCof.illuNum[c]); pLscTableProfileVigIllRes[k] = pLscTableProfileVigIll; for(int i = 0; i < calib_lsc->aLscCof.illuNum[c]; i++) { pLscTableProfileVig = (pLscTableProfileVig_t)malloc(sizeof(pLscTableProfile_t)*calib_lsc->aLscCof.illAll[c][i].tableUsedNO); memset(pLscTableProfileVig, 0, sizeof(pLscTableProfile_t)*calib_lsc->aLscCof.illAll[c][i].tableUsedNO); pLscTableProfileVigIll[i] = pLscTableProfileVig; for (int j = 0; j < calib_lsc->aLscCof.illAll[c][i].tableUsedNO; j++) { char name[LSC_PROFILE_NAME + LSC_RESOLUTION_NAME]; sprintf(name, "%s_%s", calib_lsc->aLscCof.lscResName[k], calib_lsc->aLscCof.illAll[c][i].tableUsed[j]); const CalibDb_LscTableProfile_t* pLscTableProfile = NULL; // get a lsc-profile from database ret = CamCalibDbGetLscProfileByName(calib_lsc, name, &pLscTableProfile); RETURN_RESULT_IF_DIFFERENT(ret, XCAM_RETURN_NO_ERROR); // store lsc-profile in pointer array hAlsc->pLscTableAll[c][k][i][j] = pLscTableProfile;//use the same memory //LOGE_ALSC("hAlsc->pLscTableAll2[%d][%d][%d][%d] = %0x, pLscTableProfileVig[%d] = %0x",c,k,i,j,hAlsc->pLscTableAll[c][k][i][j],j,pLscTableProfileVig[j]); LOGD_ALSC("LSC name %s r[1:2]:%d,%d \n", name, hAlsc->pLscTableAll[c][k][i][j]->LscMatrix[0].uCoeff[1], hAlsc->pLscTableAll[c][k][i][j]->LscMatrix[0].uCoeff[2]); } // order lsc-profiles by vignetting ret = AwbOrderLscProfilesByVignetting(hAlsc->pLscTableAll[c][k][i], calib_lsc->aLscCof.illAll[c][i].tableUsedNO); //RETURN_RESULT_IF_DIFFERENT(ret, XCAM_RETURN_NO_ERROR); //LOGE_ALSC("c k i %d,%d,%d,pLscTableProfileVig = %0x",c,k,i,pLscTableProfileVig); } //LOGE_ALSC("c k %d,%d,pLscTableProfileVigIll = %0x",c,k,pLscTableProfileVigIll); } //LOGE_ALSC("c %d ,pLscTableProfileVigIllRes = %0x",c,pLscTableProfileVigIllRes); } //LOGE_ALSC("pLscTableAll2 = %0x",hAlsc->pLscTableAll2); #if 0 // 1) gtet and reorder para //const CalibDb_Lsc_t *pAlscProfile = calib->lsc; for(int c=0;caLscCof.illuNum[c]; i++) { for (int k = 0; k < calib_lsc->aLscCof.lscResNum; k++) { for (int j = 0; j < calib_lsc->aLscCof.illAll[c][i].tableUsedNO; j++) { char name[LSC_PROFILE_NAME + LSC_RESOLUTION_NAME]; sprintf(name, "%s_%s", calib_lsc->aLscCof.lscResName[k], calib_lsc->aLscCof.illAll[c][i].tableUsed[j]); const CalibDb_LscTableProfile_t* pLscTableProfile = NULL; // get a lsc-profile from database ret = CamCalibDbGetLscProfileByName(calib_lsc, name, &pLscTableProfile); RETURN_RESULT_IF_DIFFERENT(ret, XCAM_RETURN_NO_ERROR); // store lsc-profile in pointer array hAlsc->pLscTableAll[c][k][i][j] = pLscTableProfile; LOGD_ALSC("LSC name %s r[1:2]:%d,%d \n", name, hAlsc->pLscTableAll[c][k][i][j]->LscMatrix[0].uCoeff[1], hAlsc->pLscTableAll[c][k][i][j]->LscMatrix[0].uCoeff[2]); } // order lsc-profiles by vignetting ret = AwbOrderLscProfilesByVignetting(hAlsc->pLscTableAll[c][k][i], calib_lsc->aLscCof.illAll[c][i].tableUsedNO); //RETURN_RESULT_IF_DIFFERENT(result, XCAM_RETURN_NO_ERROR); } } } #endif hAlsc->mCurAtt.byPass = !(calib_lsc->enable); ClearList(&hAlsc->alscRest.dominateIlluList); LOGI_ALSC("%s: (exit)\n", __FUNCTION__); return(ret); } XCamReturn AlscInit(alsc_handle_t *hAlsc, const CamCalibDbContext_t* calib) { LOGI_ALSC("%s: (enter)\n", __FUNCTION__); XCamReturn ret = XCAM_RETURN_NO_ERROR; *hAlsc = (alsc_context_t*)malloc(sizeof(alsc_context_t)); alsc_context_t* alsc_context = *hAlsc; memset(alsc_context, 0, sizeof(alsc_context_t)); if(calib == NULL) { return XCAM_RETURN_ERROR_FAILED; } const CalibDb_Lsc_t *calib_lsc = &calib->lsc; alsc_context->calibLsc = calib_lsc; alsc_context->alscSwInfo.sensorGain = 1.0; alsc_context->alscSwInfo.awbIIRDampCoef = 0; alsc_context->alscSwInfo.grayMode = false; alsc_context->alscSwInfo.varianceLuma = 255; alsc_context->alscSwInfo.awbConverged = false; int caseIndex = USED_FOR_CASE_NORMAL; alsc_context->alscRest.caseIndex = caseIndex; alsc_context->count = 0; alsc_context->mCurAtt.mode = RK_AIQ_LSC_MODE_AUTO; alsc_context->alscSwInfo.prepare_type = RK_AIQ_ALGO_CONFTYPE_UPDATECALIB | RK_AIQ_ALGO_CONFTYPE_NEEDRESET; ret = UpdateLscCalibPara(alsc_context); LOGI_ALSC("%s: (exit)\n", __FUNCTION__); return(ret); } XCamReturn AlscRelease(alsc_handle_t hAlsc) { LOGI_ALSC("%s: (enter)\n", __FUNCTION__); XCamReturn ret = XCAM_RETURN_NO_ERROR; pLscTableProfileVig_t pLscTableProfileVig; pLscTableProfileVigIll_t pLscTableProfileVigIll; pLscTableProfileVigIllRes_t pLscTableProfileVigIllRes; for(int c=0;cpLscTableAll[c]; for (int k = 0; k < hAlsc->calibLsc->aLscCof.lscResNum; k++) { pLscTableProfileVigIll = pLscTableProfileVigIllRes[k]; for(int i = 0; i < hAlsc->calibLsc->aLscCof.illuNum[c]; i++) { pLscTableProfileVig = pLscTableProfileVigIll[i]; for (int j = 0; j < hAlsc->calibLsc->aLscCof.illAll[c][i].tableUsedNO; j++) { //free } //LOGE_ALSC("c k i %d,%d,%d,pLscTableProfileVig = %0x",c,k,i,pLscTableProfileVig); if(pLscTableProfileVig){ free(pLscTableProfileVig); pLscTableProfileVig = NULL; } } //LOGE_ALSC("c k %d,%d,pLscTableProfileVigIll = %0x",c,k,pLscTableProfileVigIll); if(pLscTableProfileVigIll){ free(pLscTableProfileVigIll); pLscTableProfileVigIll = NULL; } } if(pLscTableProfileVigIllRes){ free(pLscTableProfileVigIllRes); pLscTableProfileVigIllRes = NULL; } //LOGE_ALSC("c %d ,pLscTableProfileVigIllRes = %0x",c,pLscTableProfileVigIllRes); } if(hAlsc->pLscTableAll){ free(hAlsc->pLscTableAll); hAlsc->pLscTableAll = NULL; } //LOGE_ALSC("pLscTableAll2 = %0x",hAlsc->pLscTableAll2); ClearList(&hAlsc->alscRest.dominateIlluList); free(hAlsc); LOGI_ALSC("%s: (exit)\n", __FUNCTION__); return(ret); } XCamReturn AlscPrepare(alsc_handle_t hAlsc) { LOGI_ALSC("%s: (enter)\n", __FUNCTION__); XCamReturn ret = XCAM_RETURN_NO_ERROR; ret = UpdateLscCalibPara(hAlsc); RETURN_RESULT_IF_DIFFERENT(ret, XCAM_RETURN_NO_ERROR); int resIdx; ret = CamCalibDbGetLscResIdxByName( hAlsc->calibLsc, hAlsc->curResName, &resIdx ); RETURN_RESULT_IF_DIFFERENT(ret, XCAM_RETURN_NO_ERROR); hAlsc->alscRest.resIdx = resIdx; const CalibDb_LscTableProfile_t* pLscProfile1 = hAlsc->pLscTableAll[USED_FOR_CASE_NORMAL][resIdx][0][0]; memcpy(&hAlsc->lscHwConf.x_grad_tbl[0], &pLscProfile1-> LscXGradTbl[0], sizeof(pLscProfile1-> LscXGradTbl)); memcpy(&hAlsc->lscHwConf.y_grad_tbl[0], &pLscProfile1-> LscYGradTbl[0], sizeof(pLscProfile1-> LscYGradTbl)); memcpy(&hAlsc->lscHwConf.x_size_tbl[0], &pLscProfile1-> LscXSizeTbl[0], sizeof(pLscProfile1-> LscXSizeTbl)); memcpy(&hAlsc->lscHwConf.y_size_tbl[0], &pLscProfile1-> LscYSizeTbl[0], sizeof(pLscProfile1-> LscYSizeTbl)); LOGI_ALSC("%s: (exit)\n", __FUNCTION__); return ret; } XCamReturn AlscPreProc(alsc_handle_t hAlsc) { LOG1_ALSC("%s: (enter)\n", __FUNCTION__); XCamReturn ret = XCAM_RETURN_NO_ERROR; LOG1_ALSC("%s: (exit)\n", __FUNCTION__); return(ret); } XCamReturn AlscProcessing(alsc_handle_t hAlsc) { LOG1_ALSC("%s: (enter)\n", __FUNCTION__); XCamReturn ret = XCAM_RETURN_NO_ERROR; LOG1_ALSC("%s: (exit)\n", __FUNCTION__); return(ret); } RKAIQ_END_DECLARE