You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1213 lines
57 KiB

/*
* rk_aiq_algo_debayer_itf.c
*
* Copyright (c) 2024 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.h"
#include "drc_types_prvt.h"
#include "xcam_log.h"
#include "RkAiqCalibDbTypes.h"
#include "RkAiqCalibDbTypesV2.h"
#include "RkAiqCalibDbV2Helper.h"
#include "RkAiqHandle.h"
#include "interpolation.h"
//RKAIQ_BEGIN_DECLARE
#if RKAIQ_HAVE_DRC_V12
XCamReturn DrcSelectParam(DrcContext_t* pDrcCtx, drc_param_t* out, int iso);
bool DrcDamping(drc_param_t* out, CurrData_t* pCurrData, int FrameID);
void DrcExpoParaProcessing(DrcContext_t* pDrcCtx, drc_param_t* out);
#endif
#if RKAIQ_HAVE_DRC_V20
XCamReturn DrcSelectParam(DrcContext_t* pDrcCtx, drc_param_t* out, int iso);
void DrcAutoProcessing(drc_param_t* out, drc_param_auto_t* paut, float iso);
bool DrcDamping(drc_param_t* out, CurrData_t* pCurrData, int FrameID);
void DrcExpoParaProcessing(DrcContext_t* pDrcCtx, drc_param_t* out, int iso);
#endif
static XCamReturn
create_context
(
RkAiqAlgoContext** context,
const AlgoCtxInstanceCfg* cfg
)
{
XCamReturn result = XCAM_RETURN_NO_ERROR;
CamCalibDbV2Context_t *pCalibDbV2 = cfg->calibv2;
DrcContext_t *ctx = new DrcContext_t();
if (ctx == NULL) {
LOGE_ATMO( "%s: create Drc context fail!\n", __FUNCTION__);
return XCAM_RETURN_ERROR_MEM;
}
ctx->isCapture = false;
ctx->isDampStable = true;
ctx->isReCal_ = true;
ctx->prepare_params = NULL;
ctx->drc_attrib =
(drc_api_attrib_t*)(CALIBDBV2_GET_MODULE_PTR(pCalibDbV2, drc));
*context = (RkAiqAlgoContext* )ctx;
LOGV_ATMO("%s: (exit)\n", __FUNCTION__ );
return result;
}
static XCamReturn
destroy_context
(
RkAiqAlgoContext* context
)
{
XCamReturn result = XCAM_RETURN_NO_ERROR;
DrcContext_t* pDrcCtx = (DrcContext_t*)context;
delete pDrcCtx;
return result;
}
static XCamReturn
prepare
(
RkAiqAlgoCom* params
)
{
XCamReturn result = XCAM_RETURN_NO_ERROR;
DrcContext_t* pDrcCtx = (DrcContext_t*)params->ctx;
RkAiqAlgoConfigDrc* DrcCfgParam = (RkAiqAlgoConfigDrc*)params;
if (DrcCfgParam->working_mode < RK_AIQ_WORKING_MODE_ISP_HDR2)
pDrcCtx->FrameNumber = LINEAR_NUM;
else if (DrcCfgParam->working_mode < RK_AIQ_WORKING_MODE_ISP_HDR3 &&
DrcCfgParam->working_mode >= RK_AIQ_WORKING_MODE_ISP_HDR2)
pDrcCtx->FrameNumber = HDR_2X_NUM;
else
pDrcCtx->FrameNumber = HDR_3X_NUM;
if (DrcCfgParam->compr_bit) {
pDrcCtx->FrameNumber = SENSOR_MGE;
pDrcCtx->compr_bit = DrcCfgParam->compr_bit;
if (pDrcCtx->compr_bit > ISP_HDR_BIT_NUM_MAX)
LOGE_ATMO("%s: SensorMgeBitNum(%d) > %d!!!\n", __FUNCTION__, pDrcCtx->compr_bit,
ISP_HDR_BIT_NUM_MAX);
if (pDrcCtx->compr_bit < ISP_HDR_BIT_NUM_MIN)
LOGE_ATMO("%s: SensorMgeBitNum(%d) < %d!!!\n", __FUNCTION__, pDrcCtx->compr_bit,
ISP_HDR_BIT_NUM_MIN);
pDrcCtx->compr_bit =
CLIP(pDrcCtx->compr_bit, ISP_HDR_BIT_NUM_MAX, ISP_HDR_BIT_NUM_MIN);
}
if(!!(params->u.prepare.conf_type & RK_AIQ_ALGO_CONFTYPE_UPDATECALIB )){
// just update calib ptr
if (params->u.prepare.conf_type & RK_AIQ_ALGO_CONFTYPE_UPDATECALIB_PTR) {
pDrcCtx->drc_attrib =
(drc_api_attrib_t*)(CALIBDBV2_GET_MODULE_PTR(params->u.prepare.calibv2, drc));
return XCAM_RETURN_NO_ERROR;
}
} else if (params->u.prepare.conf_type & RK_AIQ_ALGO_CONFTYPE_CHANGERES) {
pDrcCtx->isCapture = true;
}
pDrcCtx->drc_attrib =
(drc_api_attrib_t*)(CALIBDBV2_GET_MODULE_PTR(params->u.prepare.calibv2, drc));
pDrcCtx->prepare_params = &params->u.prepare;
pDrcCtx->isReCal_ = true;
return result;
}
static XCamReturn
processing
(
const RkAiqAlgoCom* inparams,
RkAiqAlgoResCom* outparams
)
{
XCamReturn result = XCAM_RETURN_NO_ERROR;
DrcContext_t* pDrcCtx = (DrcContext_t*)inparams->ctx;
pDrcCtx->FrameID = inparams->frame_id;
drc_api_attrib_t* drc_attrib = pDrcCtx->drc_attrib;
RkAiqAlgoProcResDrc* pDrcProcResParams = (RkAiqAlgoProcResDrc*)outparams;
RkAiqAlgoProcDrc* drc_proc_param = (RkAiqAlgoProcDrc*)inparams;
pDrcCtx->blc_ob_enable = drc_proc_param->blc_ob_enable;
pDrcCtx->isp_ob_predgain = drc_proc_param->isp_ob_predgain;
pDrcCtx->hw_transCfg_trans_mode = drc_proc_param->hw_transCfg_trans_mode;
pDrcCtx->hw_transCfg_transOfDrc_offset = drc_proc_param->hw_transCfg_transOfDrc_offset;
LOGV_ATMO("%s: (enter)\n", __FUNCTION__);
if (!drc_attrib) {
LOGE_ATMO("drc_attrib is NULL !");
return XCAM_RETURN_ERROR_MEM;
}
if (drc_attrib->opMode != RK_AIQ_OP_MODE_AUTO) {
LOGE_ATMO("mode is %d, not auto mode, ignore", drc_attrib->opMode);
return XCAM_RETURN_NO_ERROR;
}
if (inparams->u.proc.is_attrib_update) {
pDrcCtx->isReCal_ = true;
}
if (pDrcCtx->isCapture) {
LOGD_ATMO("%s: It's capturing, using pre frame params\n", __func__);
pDrcCtx->isCapture = false;
return XCAM_RETURN_NO_ERROR;
}
if (pDrcCtx->FrameNumber == HDR_2X_NUM || pDrcCtx->FrameNumber == HDR_3X_NUM ||
pDrcCtx->FrameNumber == SENSOR_MGE)
outparams->en = true;
else if (pDrcCtx->FrameNumber == LINEAR_NUM) {
if (pDrcCtx->blc_ob_enable)
outparams->en = true;
else {
if (drc_attrib->opMode == RK_AIQ_OP_MODE_AUTO) {
outparams->en = drc_attrib->en;
} else {
outparams->en = false;
}
}
}
if (outparams->en)
pDrcCtx->NextData.AEData.LongFrmMode = drc_proc_param->LongFrmMode;
if(pDrcCtx->FrameNumber == LINEAR_NUM) {
pDrcCtx->NextData.AEData.SExpo =
drc_proc_param->com.u.proc.nxtExp->LinearExp.exp_real_params.analog_gain *
drc_proc_param->com.u.proc.nxtExp->LinearExp.exp_real_params.digital_gain *
drc_proc_param->com.u.proc.nxtExp->LinearExp.exp_real_params.isp_dgain *
drc_proc_param->com.u.proc.nxtExp->LinearExp.exp_real_params.integration_time;
if (pDrcCtx->NextData.AEData.SExpo < FLT_EPSILON) {
pDrcCtx->NextData.AEData.SExpo =
drc_proc_param->com.u.proc.curExp->LinearExp.exp_real_params.analog_gain *
drc_proc_param->com.u.proc.curExp->LinearExp.exp_real_params.digital_gain *
drc_proc_param->com.u.proc.curExp->LinearExp.exp_real_params.isp_dgain *
drc_proc_param->com.u.proc.curExp->LinearExp.exp_real_params.integration_time;
}
pDrcCtx->NextData.AEData.MExpo = pDrcCtx->NextData.AEData.SExpo;
pDrcCtx->NextData.AEData.LExpo = pDrcCtx->NextData.AEData.SExpo;
}
else if(pDrcCtx->FrameNumber == HDR_2X_NUM) {
pDrcCtx->NextData.AEData.SExpo =
drc_proc_param->com.u.proc.nxtExp->HdrExp[0].exp_real_params.analog_gain *
drc_proc_param->com.u.proc.nxtExp->HdrExp[0].exp_real_params.digital_gain *
drc_proc_param->com.u.proc.nxtExp->HdrExp[0].exp_real_params.isp_dgain *
drc_proc_param->com.u.proc.nxtExp->HdrExp[0].exp_real_params.integration_time;
pDrcCtx->NextData.AEData.MExpo =
drc_proc_param->com.u.proc.nxtExp->HdrExp[1].exp_real_params.analog_gain *
drc_proc_param->com.u.proc.nxtExp->HdrExp[1].exp_real_params.digital_gain *
drc_proc_param->com.u.proc.nxtExp->HdrExp[1].exp_real_params.isp_dgain *
drc_proc_param->com.u.proc.nxtExp->HdrExp[1].exp_real_params.integration_time;
if (pDrcCtx->NextData.AEData.SExpo < FLT_EPSILON) {
pDrcCtx->NextData.AEData.SExpo =
drc_proc_param->com.u.proc.curExp->HdrExp[0].exp_real_params.analog_gain *
drc_proc_param->com.u.proc.curExp->HdrExp[0].exp_real_params.digital_gain *
drc_proc_param->com.u.proc.curExp->HdrExp[0].exp_real_params.isp_dgain *
drc_proc_param->com.u.proc.curExp->HdrExp[0].exp_real_params.integration_time;
pDrcCtx->NextData.AEData.MExpo =
drc_proc_param->com.u.proc.curExp->HdrExp[1].exp_real_params.analog_gain *
drc_proc_param->com.u.proc.curExp->HdrExp[1].exp_real_params.digital_gain *
drc_proc_param->com.u.proc.curExp->HdrExp[1].exp_real_params.isp_dgain *
drc_proc_param->com.u.proc.curExp->HdrExp[1].exp_real_params.integration_time;
}
pDrcCtx->NextData.AEData.LExpo = pDrcCtx->NextData.AEData.MExpo;
}
else if(pDrcCtx->FrameNumber == HDR_3X_NUM) {
pDrcCtx->NextData.AEData.SExpo =
drc_proc_param->com.u.proc.nxtExp->HdrExp[0].exp_real_params.analog_gain *
drc_proc_param->com.u.proc.nxtExp->HdrExp[0].exp_real_params.digital_gain *
drc_proc_param->com.u.proc.nxtExp->HdrExp[0].exp_real_params.isp_dgain *
drc_proc_param->com.u.proc.nxtExp->HdrExp[0].exp_real_params.integration_time;
pDrcCtx->NextData.AEData.MExpo =
drc_proc_param->com.u.proc.nxtExp->HdrExp[1].exp_real_params.analog_gain *
drc_proc_param->com.u.proc.nxtExp->HdrExp[1].exp_real_params.digital_gain *
drc_proc_param->com.u.proc.nxtExp->HdrExp[1].exp_real_params.isp_dgain *
drc_proc_param->com.u.proc.nxtExp->HdrExp[1].exp_real_params.integration_time;
pDrcCtx->NextData.AEData.LExpo =
drc_proc_param->com.u.proc.nxtExp->HdrExp[2].exp_real_params.analog_gain *
drc_proc_param->com.u.proc.nxtExp->HdrExp[2].exp_real_params.digital_gain *
drc_proc_param->com.u.proc.nxtExp->HdrExp[2].exp_real_params.isp_dgain *
drc_proc_param->com.u.proc.nxtExp->HdrExp[2].exp_real_params.integration_time;
if (pDrcCtx->NextData.AEData.SExpo < FLT_EPSILON) {
pDrcCtx->NextData.AEData.SExpo =
drc_proc_param->com.u.proc.curExp->HdrExp[0].exp_real_params.analog_gain *
drc_proc_param->com.u.proc.curExp->HdrExp[0].exp_real_params.digital_gain *
drc_proc_param->com.u.proc.curExp->HdrExp[0].exp_real_params.isp_dgain *
drc_proc_param->com.u.proc.curExp->HdrExp[0].exp_real_params.integration_time;
pDrcCtx->NextData.AEData.MExpo =
drc_proc_param->com.u.proc.curExp->HdrExp[1].exp_real_params.analog_gain *
drc_proc_param->com.u.proc.curExp->HdrExp[1].exp_real_params.digital_gain *
drc_proc_param->com.u.proc.curExp->HdrExp[1].exp_real_params.isp_dgain *
drc_proc_param->com.u.proc.curExp->HdrExp[1].exp_real_params.integration_time;
pDrcCtx->NextData.AEData.LExpo =
drc_proc_param->com.u.proc.curExp->HdrExp[2].exp_real_params.analog_gain *
drc_proc_param->com.u.proc.curExp->HdrExp[2].exp_real_params.digital_gain *
drc_proc_param->com.u.proc.curExp->HdrExp[2].exp_real_params.isp_dgain *
drc_proc_param->com.u.proc.curExp->HdrExp[2].exp_real_params.integration_time;
}
} else if (pDrcCtx->FrameNumber == SENSOR_MGE) {
pDrcCtx->NextData.AEData.MExpo =
drc_proc_param->com.u.proc.nxtExp->LinearExp.exp_real_params.analog_gain *
drc_proc_param->com.u.proc.nxtExp->LinearExp.exp_real_params.digital_gain *
drc_proc_param->com.u.proc.nxtExp->LinearExp.exp_real_params.isp_dgain *
drc_proc_param->com.u.proc.nxtExp->LinearExp.exp_real_params.integration_time;
if (pDrcCtx->NextData.AEData.MExpo < FLT_EPSILON) {
pDrcCtx->NextData.AEData.MExpo =
drc_proc_param->com.u.proc.curExp->LinearExp.exp_real_params.analog_gain *
drc_proc_param->com.u.proc.curExp->LinearExp.exp_real_params.digital_gain *
drc_proc_param->com.u.proc.curExp->LinearExp.exp_real_params.isp_dgain *
drc_proc_param->com.u.proc.curExp->LinearExp.exp_real_params.integration_time;
}
pDrcCtx->NextData.AEData.LExpo = pDrcCtx->NextData.AEData.MExpo;
pDrcCtx->NextData.AEData.SExpo =
pDrcCtx->NextData.AEData.MExpo /
pow(2.0f, float(pDrcCtx->compr_bit - ISP_HDR_BIT_NUM_MIN));
}
if (pDrcCtx->NextData.AEData.SExpo > FLT_EPSILON) {
pDrcCtx->NextData.AEData.L2S_Ratio =
pDrcCtx->NextData.AEData.LExpo / pDrcCtx->NextData.AEData.SExpo;
if (pDrcCtx->NextData.AEData.L2S_Ratio < RATIO_DEFAULT) {
LOGE_ATMO("%s: Next L2S_Ratio:%f is less than 1.0x, clip to 1.0x!!!\n",
__FUNCTION__, pDrcCtx->NextData.AEData.L2S_Ratio);
pDrcCtx->NextData.AEData.L2S_Ratio = RATIO_DEFAULT;
}
pDrcCtx->NextData.AEData.M2S_Ratio =
pDrcCtx->NextData.AEData.MExpo / pDrcCtx->NextData.AEData.SExpo;
if (pDrcCtx->NextData.AEData.M2S_Ratio < RATIO_DEFAULT) {
LOGE_ATMO("%s: Next M2S_Ratio:%f is less than 1.0x, clip to 1.0x!!!\n",
__FUNCTION__, pDrcCtx->NextData.AEData.M2S_Ratio);
pDrcCtx->NextData.AEData.M2S_Ratio = RATIO_DEFAULT;
}
}
else
LOGE_ATMO("%s: Next Short frame for drc expo sync is %f!!!\n", __FUNCTION__,
pDrcCtx->NextData.AEData.SExpo);
if (pDrcCtx->NextData.AEData.MExpo > FLT_EPSILON) {
pDrcCtx->NextData.AEData.L2M_Ratio =
pDrcCtx->NextData.AEData.LExpo / pDrcCtx->NextData.AEData.MExpo;
if (pDrcCtx->NextData.AEData.L2M_Ratio < RATIO_DEFAULT) {
LOGE_ATMO("%s: Next L2M_Ratio:%f is less than 1.0x, clip to 1.0x!!!\n",
__FUNCTION__, pDrcCtx->NextData.AEData.L2M_Ratio);
pDrcCtx->NextData.AEData.L2M_Ratio = RATIO_DEFAULT;
}
} else
LOGE_ATMO("%s: Next Midlle frame for drc expo sync is %f!!!\n", __FUNCTION__,
pDrcCtx->NextData.AEData.MExpo);
//clip for long frame mode
if (pDrcCtx->NextData.AEData.LongFrmMode) {
pDrcCtx->NextData.AEData.L2S_Ratio = LONG_FRAME_MODE_RATIO;
pDrcCtx->NextData.AEData.M2S_Ratio = LONG_FRAME_MODE_RATIO;
pDrcCtx->NextData.AEData.L2M_Ratio = LONG_FRAME_MODE_RATIO;
}
// clip L2M_ratio to 32x
if (pDrcCtx->NextData.AEData.L2M_Ratio > AE_RATIO_L2M_MAX) {
LOGE_ATMO("%s: Next L2M_ratio:%f out of range, clip to 32.0x!!!\n", __FUNCTION__,
pDrcCtx->NextData.AEData.L2M_Ratio);
pDrcCtx->NextData.AEData.L2M_Ratio = AE_RATIO_L2M_MAX;
}
// clip L2S_ratio
if (pDrcCtx->NextData.AEData.L2S_Ratio > AE_RATIO_MAX) {
LOGE_ATMO("%s: Next L2S_Ratio:%f out of range, clip to 256.0x!!!\n", __FUNCTION__,
pDrcCtx->NextData.AEData.L2S_Ratio);
pDrcCtx->NextData.AEData.L2S_Ratio = AE_RATIO_MAX;
}
// clip L2M_ratio and M2S_Ratio
if (pDrcCtx->NextData.AEData.L2M_Ratio * pDrcCtx->NextData.AEData.M2S_Ratio >
AE_RATIO_MAX) {
LOGE_ATMO("%s: Next L2M_Ratio*M2S_Ratio:%f out of range, clip to 256.0x!!!\n",
__FUNCTION__,
pDrcCtx->NextData.AEData.L2M_Ratio * pDrcCtx->NextData.AEData.M2S_Ratio);
pDrcCtx->NextData.AEData.M2S_Ratio =
AE_RATIO_MAX / pDrcCtx->NextData.AEData.L2M_Ratio;
}
int iso = inparams->u.proc.iso;
if (pDrcCtx->FrameNumber == LINEAR_NUM&&
drc_proc_param->blc_ob_enable &&
drc_proc_param->isp_ob_predgain >= ISP_PREDGAIN_DEFAULT)
iso = iso * drc_proc_param->isp_ob_predgain;
bool init = inparams->u.proc.init;
float delta_iso = (float)abs(iso - pDrcCtx->iso);
delta_iso /= (float)pDrcCtx->iso;
outparams->cfg_update = false;
if (inparams->u.proc.is_bw_sensor) {
drc_attrib->en = false;
outparams->cfg_update = init ? true : false;
return XCAM_RETURN_NO_ERROR;
}
if (delta_iso > DEFAULT_RECALCULATE_DELTA_ISO) {
pDrcCtx->isReCal_ = true;
}
bool bypass_expo_params = true;
// get bypass_expo_params
if(!pDrcCtx->CurrData.AEData.LongFrmMode !=
!pDrcCtx->NextData.AEData.LongFrmMode)
bypass_expo_params = false;
else if ((pDrcCtx->CurrData.AEData.L2M_Ratio - pDrcCtx->NextData.AEData.L2M_Ratio) >
FLT_EPSILON ||
(pDrcCtx->CurrData.AEData.L2M_Ratio - pDrcCtx->NextData.AEData.L2M_Ratio) <
-FLT_EPSILON ||
(pDrcCtx->CurrData.AEData.M2S_Ratio - pDrcCtx->NextData.AEData.M2S_Ratio) >
FLT_EPSILON ||
(pDrcCtx->CurrData.AEData.M2S_Ratio - pDrcCtx->NextData.AEData.M2S_Ratio) <
-FLT_EPSILON ||
(pDrcCtx->CurrData.AEData.L2S_Ratio - pDrcCtx->NextData.AEData.L2S_Ratio) >
FLT_EPSILON ||
(pDrcCtx->CurrData.AEData.L2S_Ratio - pDrcCtx->NextData.AEData.L2S_Ratio) <
-FLT_EPSILON)
bypass_expo_params = false;
else
bypass_expo_params = true;
if (pDrcCtx->isReCal_ || !bypass_expo_params) {
#if RKAIQ_HAVE_DRC_V12
DrcSelectParam(pDrcCtx, pDrcProcResParams->drcRes, iso);
DrcExpoParaProcessing(pDrcCtx, pDrcProcResParams->drcRes);
#endif
#if RKAIQ_HAVE_DRC_V20
DrcSelectParam(pDrcCtx, pDrcProcResParams->drcRes, iso);
DrcExpoParaProcessing(pDrcCtx, pDrcProcResParams->drcRes, iso);
#endif
outparams->cfg_update = true;
outparams->en = drc_attrib->en;
outparams->bypass = drc_attrib->bypass;
LOGI_ATMO("drc en:%d, bypass:%d", outparams->en, outparams->bypass);
}
pDrcCtx->iso = iso;
pDrcCtx->isReCal_ = false;
pDrcCtx->CurrData.AEData.LongFrmMode = pDrcCtx->NextData.AEData.LongFrmMode;
pDrcCtx->CurrData.AEData.L2M_Ratio = pDrcCtx->NextData.AEData.L2M_Ratio;
pDrcCtx->CurrData.AEData.M2S_Ratio = pDrcCtx->NextData.AEData.M2S_Ratio;
pDrcCtx->CurrData.AEData.L2S_Ratio = pDrcCtx->NextData.AEData.L2S_Ratio;
LOGV_ATMO("%s: (exit)\n", __FUNCTION__ );
return XCAM_RETURN_NO_ERROR;
}
#if RKAIQ_HAVE_DRC_V12
XCamReturn DrcSelectParam
(
DrcContext_t* pDrcCtx,
drc_param_t* out, int iso)
{
LOGI_ATMO("%s(%d): enter!\n", __FUNCTION__, __LINE__);
if(pDrcCtx == NULL) {
LOGE_ATMO("%s(%d): null pointer\n", __FUNCTION__, __LINE__);
return XCAM_RETURN_ERROR_PARAM;
}
drc_param_auto_t* paut = &pDrcCtx->drc_attrib->stAuto;
int i = 0;
int iso_low = 0, iso_high = 0, ilow = 0, ihigh = 0;
float ratio = 0.0f;
pre_interp(iso, NULL, 0, ilow, ihigh, ratio);
out->dyn.DrcGain.DrcGain = interpolation_f32(paut->dyn[ilow].DrcGain.DrcGain,
paut->dyn[ihigh].DrcGain.DrcGain, ratio);
out->dyn.DrcGain.Alpha = interpolation_f32(paut->dyn[ilow].DrcGain.Alpha,
paut->dyn[ihigh].DrcGain.Alpha, ratio);
out->dyn.DrcGain.Clip = interpolation_f32(paut->dyn[ilow].DrcGain.Clip,
paut->dyn[ihigh].DrcGain.Clip, ratio);
out->dyn.HiLightData.Strength = interpolation_f32(paut->dyn[ilow].HiLightData.Strength,
paut->dyn[ihigh].HiLightData.Strength, ratio);
out->dyn.HiLightData.gas_t = interpolation_f32(paut->dyn[ilow].HiLightData.gas_t,
paut->dyn[ihigh].HiLightData.gas_t, ratio);
out->dyn.LocalData.LocalWeit = interpolation_f32(paut->dyn[ilow].LocalData.LocalWeit,
paut->dyn[ihigh].LocalData.LocalWeit, ratio);
out->dyn.LocalData.GlobalContrast = interpolation_f32(paut->dyn[ilow].LocalData.GlobalContrast,
paut->dyn[ihigh].LocalData.GlobalContrast, ratio);
out->dyn.LocalData.LoLitContrast = interpolation_f32(paut->dyn[ilow].LocalData.LoLitContrast,
paut->dyn[ihigh].LocalData.LoLitContrast, ratio);
out->dyn.LocalData.LocalAutoEnable = paut->dyn[ilow].LocalData.LocalAutoEnable;
out->dyn.LocalData.LocalAutoWeit = interpolation_f32(paut->dyn[ilow].LocalData.LocalAutoWeit,
paut->dyn[ihigh].LocalData.LocalAutoWeit, ratio);
// get MotionStr
out->dyn.MotionData.MotionStr = paut->dyn[0].MotionData.MotionStr;
// compress
out->sta.CompressSetting.Mode = paut->sta.CompressSetting.Mode;
for (int i = 0; i < ADRC_Y_NUM; i++)
out->sta.CompressSetting.Manual_curve[i] = paut->sta.CompressSetting.Manual_curve[i];
out->sta.LocalSetting.curPixWeit = paut->sta.LocalSetting.curPixWeit;
out->sta.LocalSetting.preFrameWeit = paut->sta.LocalSetting.preFrameWeit;
out->sta.LocalSetting.Range_sgm_pre = paut->sta.LocalSetting.Range_sgm_pre;
out->sta.LocalSetting.Space_sgm_pre = paut->sta.LocalSetting.Space_sgm_pre;
out->sta.LocalSetting.Range_force_sgm = paut->sta.LocalSetting.Range_force_sgm;
out->sta.LocalSetting.Range_sgm_cur = paut->sta.LocalSetting.Range_sgm_cur;
out->sta.LocalSetting.Space_sgm_cur = paut->sta.LocalSetting.Space_sgm_cur;
// scale y
for (int i = 0; i < DRC_Y_NUM; i++)
out->sta.Scale_y[i] =
(unsigned short)paut->sta.Scale_y[i];
out->sta.sw_drc_byPass_thred = paut->sta.sw_drc_byPass_thred;
out->sta.Edge_Weit = paut->sta.Edge_Weit;
out->sta.IIR_frame =
(float)MIN(pDrcCtx->FrameID + 1, (uint32_t)paut->sta.IIR_frame);
out->sta.damp = paut->sta.damp;
out->sta.OutPutLongFrame =
pDrcCtx->NextData.AEData.LongFrmMode || paut->sta.OutPutLongFrame;
// drc v12 add
out->sta.HiLight.gas_l0 = paut->sta.HiLight.gas_l0;
out->sta.HiLight.gas_l1 = paut->sta.HiLight.gas_l1;
out->sta.HiLight.gas_l2 = paut->sta.HiLight.gas_l2;
out->sta.HiLight.gas_l3 = paut->sta.HiLight.gas_l3;
pDrcCtx->isDampStable =
DrcDamping(out, &pDrcCtx->CurrData, pDrcCtx->FrameID);
// clip drc gain
if (pDrcCtx->FrameNumber == HDR_2X_NUM || pDrcCtx->FrameNumber == HDR_3X_NUM) {
if (pDrcCtx->NextData.AEData.L2S_Ratio * out->dyn.DrcGain.DrcGain >
MAX_AE_DRC_GAIN) {
out->dyn.DrcGain.DrcGain =
MAX(MAX_AE_DRC_GAIN / pDrcCtx->NextData.AEData.L2S_Ratio, GAINMIN);
LOGI_ATMO("%s: AERatio*DrcGain > 256x, DrcGain Clip to %f!!!\n", __FUNCTION__,
out->dyn.DrcGain.DrcGain);
}
} else if (pDrcCtx->FrameNumber == LINEAR_NUM) {
if (pDrcCtx->isp_ob_predgain * out->dyn.DrcGain.DrcGain > MAX_AE_DRC_GAIN) {
if (pDrcCtx->isp_ob_predgain > MAX_AE_DRC_GAIN)
LOGE_ATMO("%s: predgain > 256x!!!\n", __FUNCTION__);
else
out->dyn.DrcGain.DrcGain =
MAX(MAX_AE_DRC_GAIN / pDrcCtx->isp_ob_predgain, GAINMIN);
LOGI_ATMO("%s: predgain*DrcGain > 256x, DrcGain clip to %f!!!\n", __FUNCTION__,
out->dyn.DrcGain.DrcGain);
}
} else if (pDrcCtx->FrameNumber == SENSOR_MGE) {
if (pow(2.0f, float(pDrcCtx->compr_bit - ISP_HDR_BIT_NUM_MIN)) *
out->dyn.DrcGain.DrcGain > MAX_AE_DRC_GAIN) {
if (pow(2.0f, float(pDrcCtx->compr_bit - ISP_HDR_BIT_NUM_MIN)) > MAX_AE_DRC_GAIN)
LOGE_ATMO("%s: SensorMgeRatio > 256x!!!\n", __FUNCTION__);
else
out->dyn.DrcGain.DrcGain = MAX(
MAX_AE_DRC_GAIN / pow(2.0f, float(pDrcCtx->compr_bit - ISP_HDR_BIT_NUM_MIN)),
GAINMIN);
LOGI_ATMO("%s: SensorMgeRatio*DrcGain > 256x, DrcGain clip to %f!!!\n", __FUNCTION__,
out->dyn.DrcGain.DrcGain);
}
}
// clip gas_l0~3
if (out->sta.HiLight.gas_l0 == GAS_L_MAX) {
LOGE_ATMO("%s: gas_l0 equals %d, use default value\n", __FUNCTION__, GAS_L_MAX);
out->sta.HiLight.gas_l0 = GAS_L0_DEFAULT;
out->sta.HiLight.gas_l1 = GAS_L1_DEFAULT;
out->sta.HiLight.gas_l2 = GAS_L2_DEFAULT;
out->sta.HiLight.gas_l3 = GAS_L3_DEFAULT;
}
if ((out->sta.HiLight.gas_l0 + 2 * out->sta.HiLight.gas_l1 +
out->sta.HiLight.gas_l2 + 2 * out->sta.HiLight.gas_l3) !=
GAS_L_MAX) {
// LOGE_ATMO("%s: gas_l0 + gas_l1 + gas_l2 + gas_l3 DO NOT equal %d, use default value\n",
// __FUNCTION__, GAS_L_MAX);
out->sta.HiLight.gas_l0 = GAS_L0_DEFAULT;
out->sta.HiLight.gas_l1 = GAS_L1_DEFAULT;
out->sta.HiLight.gas_l2 = GAS_L2_DEFAULT;
out->sta.HiLight.gas_l3 = GAS_L3_DEFAULT;
}
out->sta.delta_scalein = DELTA_SCALEIN_FIX;
out->sta.offset_pow2 = SW_DRC_OFFSET_POW2_FIX;
float tmp = 0.0f;
/*luma[i] = pow((1.0f - luma[i] / 4096.0f), 2.0f)*/
float luma[DRC_Y_NUM] = {1.0f, 0.8789f, 0.7656f, 0.6602f, 0.5625f, 0.4727f,
0.3906f, 0.3164f, 0.2500f, 0.1914f, 0.1406f, 0.0977f,
0.0625f, 0.0352f, 0.0156f, 0.0039f, 0.0f};
for (int i = 0; i < DRC_Y_NUM; ++i) {
tmp = 1 - out->dyn.DrcGain.Alpha * luma[i];
if (pDrcCtx->blc_ob_enable)
tmp = 1024.0f * pow(out->dyn.DrcGain.DrcGain * pDrcCtx->isp_ob_predgain, tmp);
else
tmp = 1024.0f * pow(out->dyn.DrcGain.DrcGain, tmp);
out->sta.gain_y[i] = (unsigned short)(tmp);
}
if (pDrcCtx->drc_attrib->opMode == RK_AIQ_OP_MODE_AUTO && !pDrcCtx->isDampStable)
pDrcCtx->CurrData.dynParams = out->dyn;
LOG1_ATMO("%s:exit!\n", __FUNCTION__);
return XCAM_RETURN_NO_ERROR;
}
bool DrcDamping(drc_param_t* out, CurrData_t* pCurrData, int FrameID) {
LOG1_ATMO("%s:Enter!\n", __FUNCTION__);
bool isDampStable = false;
if (FrameID > INIT_CALC_PARAMS_NUM) {
bool isDampStable_DrcGain = false, isDampStable_Alpha = false, isDampStable_Clip = false,
isDampStable_Strength = false, isDampStable_LocalWeit = false,
isDampStable_LocalAutoWeit = false, isDampStable_GlobalContrast = false,
isDampStable_LoLitContrast = false, isDampStable_gas_t = false,
isDampStable_MotionStr = false;
if ((out->dyn.DrcGain.DrcGain - pCurrData->dynParams.DrcGain.DrcGain) <=
FLT_EPSILON &&
(out->dyn.DrcGain.DrcGain - pCurrData->dynParams.DrcGain.DrcGain) >=
-FLT_EPSILON) {
isDampStable_DrcGain = true;
} else {
out->dyn.DrcGain.DrcGain =
out->sta.damp * out->dyn.DrcGain.DrcGain +
(1.0f - out->sta.damp) * pCurrData->dynParams.DrcGain.DrcGain;
isDampStable_DrcGain = false;
}
if ((out->dyn.DrcGain.Alpha - pCurrData->dynParams.DrcGain.Alpha) <=
FLT_EPSILON &&
(out->dyn.DrcGain.Alpha - pCurrData->dynParams.DrcGain.Alpha) >=
-FLT_EPSILON) {
isDampStable_Alpha = true;
} else {
out->dyn.DrcGain.Alpha =
out->sta.damp * out->dyn.DrcGain.Alpha +
(1.0f - out->sta.damp) * pCurrData->dynParams.DrcGain.Alpha;
isDampStable_Alpha = false;
}
if ((out->dyn.DrcGain.Clip - pCurrData->dynParams.DrcGain.Clip) <=
FLT_EPSILON &&
(out->dyn.DrcGain.Clip - pCurrData->dynParams.DrcGain.Clip) >=
-FLT_EPSILON) {
isDampStable_Clip = true;
} else {
out->dyn.DrcGain.Clip =
out->sta.damp * out->dyn.DrcGain.Clip +
(1.0f - out->sta.damp) * pCurrData->dynParams.DrcGain.Clip;
isDampStable_Clip = false;
}
if ((out->dyn.HiLightData.Strength - pCurrData->dynParams.HiLightData.Strength) <=
FLT_EPSILON &&
(out->dyn.HiLightData.Strength - pCurrData->dynParams.HiLightData.Strength) >=
-FLT_EPSILON) {
isDampStable_Strength = true;
} else {
out->dyn.HiLightData.Strength =
out->sta.damp * out->dyn.HiLightData.Strength +
(1.0f - out->sta.damp) * pCurrData->dynParams.HiLightData.Strength;
isDampStable_Strength = false;
}
if ((out->dyn.LocalData.LocalWeit - pCurrData->dynParams.LocalData.LocalWeit) <=
FLT_EPSILON &&
(out->dyn.LocalData.LocalWeit - pCurrData->dynParams.LocalData.LocalWeit) >=
-FLT_EPSILON) {
isDampStable_LocalWeit = true;
} else {
out->dyn.LocalData.LocalWeit =
out->sta.damp * out->dyn.LocalData.LocalWeit +
(1.0f - out->sta.damp) * pCurrData->dynParams.LocalData.LocalWeit;
isDampStable_LocalWeit = false;
}
if ((out->dyn.LocalData.LocalAutoWeit -
pCurrData->dynParams.LocalData.LocalAutoWeit) <= FLT_EPSILON &&
(out->dyn.LocalData.LocalAutoWeit -
pCurrData->dynParams.LocalData.LocalAutoWeit) >= -FLT_EPSILON) {
isDampStable_LocalAutoWeit = true;
} else {
out->dyn.LocalData.LocalAutoWeit =
out->sta.damp * out->dyn.LocalData.LocalAutoWeit +
(1.0f - out->sta.damp) * pCurrData->dynParams.LocalData.LocalAutoWeit;
isDampStable_LocalAutoWeit = false;
}
if ((out->dyn.LocalData.GlobalContrast -
pCurrData->dynParams.LocalData.GlobalContrast) <= FLT_EPSILON &&
(out->dyn.LocalData.GlobalContrast -
pCurrData->dynParams.LocalData.GlobalContrast) >= -FLT_EPSILON) {
isDampStable_GlobalContrast = true;
} else {
out->dyn.LocalData.GlobalContrast =
out->sta.damp * out->dyn.LocalData.GlobalContrast +
(1.0f - out->sta.damp) * pCurrData->dynParams.LocalData.GlobalContrast;
isDampStable_GlobalContrast = false;
}
if ((out->dyn.LocalData.LoLitContrast -
pCurrData->dynParams.LocalData.LoLitContrast) <= FLT_EPSILON &&
(out->dyn.LocalData.LoLitContrast -
pCurrData->dynParams.LocalData.LoLitContrast) >= -FLT_EPSILON) {
isDampStable_LoLitContrast = true;
} else {
out->dyn.LocalData.LoLitContrast =
out->sta.damp * out->dyn.LocalData.LoLitContrast +
(1.0f - out->sta.damp) * pCurrData->dynParams.LocalData.LoLitContrast;
isDampStable_LoLitContrast = false;
}
// drc v12
if ((out->dyn.HiLightData.gas_t - pCurrData->dynParams.HiLightData.gas_t) <=
FLT_EPSILON &&
(out->dyn.HiLightData.gas_t - pCurrData->dynParams.HiLightData.gas_t) >=
-FLT_EPSILON) {
isDampStable_gas_t = true;
} else {
out->dyn.HiLightData.gas_t =
out->sta.damp * out->dyn.HiLightData.gas_t +
(1.0f - out->sta.damp) * pCurrData->dynParams.HiLightData.gas_t;
isDampStable_gas_t = false;
}
if ((out->dyn.MotionData.MotionStr - pCurrData->dynParams.MotionData.MotionStr) <=
FLT_EPSILON &&
(out->dyn.MotionData.MotionStr - pCurrData->dynParams.MotionData.MotionStr) >=
-FLT_EPSILON) {
isDampStable_MotionStr = true;
} else {
out->dyn.MotionData.MotionStr =
out->sta.damp * out->dyn.MotionData.MotionStr +
(1.0f - out->sta.damp) * pCurrData->dynParams.MotionData.MotionStr;
isDampStable_MotionStr = false;
}
isDampStable = isDampStable_DrcGain && isDampStable_Alpha && isDampStable_Clip &&
isDampStable_Strength && isDampStable_LocalWeit &&
isDampStable_LocalAutoWeit && isDampStable_GlobalContrast &&
isDampStable_LoLitContrast && isDampStable_gas_t && isDampStable_MotionStr;
} else
isDampStable = false;
LOG1_ATMO("%s:Eixt!\n", __FUNCTION__);
return isDampStable;
}
void DrcExpoParaProcessing(DrcContext_t* pDrcCtx, drc_param_t* out) {
LOG1_ATMO("%s:enter!\n", __FUNCTION__);
// get sw_drc_compres_scl
float adrc_gain = 1.0f;
if (pDrcCtx->FrameNumber == LINEAR_NUM && pDrcCtx->blc_ob_enable)
adrc_gain = out->dyn.DrcGain.DrcGain * pDrcCtx->isp_ob_predgain;
else
adrc_gain = out->dyn.DrcGain.DrcGain;
float log_ratio2 = log(pDrcCtx->NextData.AEData.L2S_Ratio * adrc_gain) / log(2.0f) + 12.0f;
float offsetbits_int = out->sta.offset_pow2;
float offsetbits = offsetbits_int * (1 << MFHDR_LOG_Q_BITS);
float hdrbits = log_ratio2 * (1 << MFHDR_LOG_Q_BITS);
float hdrvalidbits = hdrbits - offsetbits;
out->sta.compres_scl = (12.0f * (1 << (MFHDR_LOG_Q_BITS * 2))) / hdrvalidbits;
// get sw_drc_min_ogain
if (out->sta.OutPutLongFrame)
out->sta.sw_drc_min_ogain = 1;
else {
out->sta.sw_drc_min_ogain = 1.0f / (pDrcCtx->NextData.AEData.L2S_Ratio * adrc_gain);
}
// get sw_drc_compres_y
if (out->sta.CompressSetting.Mode == drc_COMPRESS_AUTO) {
float curveparam, curveparam2, curveparam3, tmp;
float luma2[DRC_Y_NUM] = {0.0f, 1024.0f, 2048.0f, 3072.0f, 4096.0f, 5120.0f,
6144.0f, 7168.0f, 8192.0f, 10240.0f, 12288.0f, 14336.0f,
16384.0f, 18432.0f, 20480.0f, 22528.0f, 24576.0f};
float curveTable;
float dstbits = ISP_RAW_BIT * (1 << MFHDR_LOG_Q_BITS);
float validbits = dstbits - offsetbits;
for (int i = 0; i < DRC_Y_NUM; ++i) {
curveparam =
(float)(validbits - 0.0f) / (hdrvalidbits - validbits + DRC_COMPRESS_Y_OFFSET);
curveparam2 = validbits * (1.0f + curveparam);
curveparam3 = hdrvalidbits * curveparam;
tmp = luma2[i] * hdrvalidbits / 24576.0f;
curveTable = (tmp * curveparam2 / (tmp + curveparam3));
out->sta.compres_y[i] = (unsigned short)(curveTable);
}
} else if (out->sta.CompressSetting.Mode == drc_COMPRESS_MANUAL) {
for (int i = 0; i < DRC_Y_NUM; ++i)
out->sta.compres_y[i] =
(unsigned short)(out->sta.CompressSetting.Manual_curve[i]);
}
}
#endif
#if RKAIQ_HAVE_DRC_V20
XCamReturn DrcSelectParam
(
DrcContext_t* pDrcCtx,
drc_param_t* out, int iso)
{
LOGI_ATMO("%s(%d): enter!\n", __FUNCTION__, __LINE__);
if(pDrcCtx == NULL) {
LOGE_ATMO("%s(%d): null pointer\n", __FUNCTION__, __LINE__);
return XCAM_RETURN_ERROR_PARAM;
}
drc_param_auto_t* paut = &pDrcCtx->drc_attrib->stAuto;
DrcAutoProcessing(out, paut, iso);
// pDrcCtx->isDampStable = DrcDamping(out, &pDrcCtx->CurrData, pDrcCtx->FrameID);
// clip drc gain
if (pDrcCtx->FrameNumber == HDR_2X_NUM || pDrcCtx->FrameNumber == HDR_3X_NUM) {
if (pDrcCtx->NextData.AEData.L2S_Ratio *
out->dyn.preProc.sw_drcT_toneGain_maxLimit > MAX_AE_DRC_GAIN) {
LOGE_ATMO("%s: AERatio*sw_drcT_toneGain_maxLimit > 256!!!\n", __FUNCTION__);
out->dyn.preProc.sw_drcT_toneGain_maxLimit =
MAX(MAX_AE_DRC_GAIN / pDrcCtx->NextData.AEData.L2S_Ratio, GAINMIN);
}
} else if (pDrcCtx->FrameNumber == LINEAR_NUM) {
if (pDrcCtx->isp_ob_predgain *
out->dyn.preProc.sw_drcT_toneGain_maxLimit > MAX_AE_DRC_GAIN) {
LOGE_ATMO("%s: predgain*sw_drcT_toneGain_maxLimit > 256!!!\n", __FUNCTION__);
if (pDrcCtx->isp_ob_predgain > MAX_AE_DRC_GAIN)
LOGE_ATMO("%s: predgain > 256!!!\n", __FUNCTION__);
else
out->dyn.preProc.sw_drcT_toneGain_maxLimit =
MAX(MAX_AE_DRC_GAIN / pDrcCtx->isp_ob_predgain, GAINMIN);
}
} else if (pDrcCtx->FrameNumber == SENSOR_MGE) {
if (pow(2.0f, float(pDrcCtx->compr_bit - ISP_HDR_BIT_NUM_MIN)) *
out->dyn.preProc.sw_drcT_toneGain_maxLimit > MAX_AE_DRC_GAIN) {
if (pow(2.0f, float(pDrcCtx->compr_bit - ISP_HDR_BIT_NUM_MIN)) > MAX_AE_DRC_GAIN)
LOGE_ATMO("%s: SensorMgeRatio > 256x!!!\n", __FUNCTION__);
else
out->dyn.preProc.sw_drcT_toneGain_maxLimit = MAX(
MAX_AE_DRC_GAIN / pow(2.0f, float(pDrcCtx->compr_bit - ISP_HDR_BIT_NUM_MIN)),
GAINMIN);
LOGI_ATMO(
"%s: SensorMgeRatio*sw_drcT_toneGain_maxLimit > 256x, sw_drcT_toneGain_maxLimit "
"clip to %f!!!\n",
__FUNCTION__,
out->dyn.preProc.sw_drcT_toneGain_maxLimit);
}
}
// get sw_drc_gain_y
if (out->dyn.preProc.sw_drcT_toneCurve_mode == drc_cfgCurveCtrlCoeff_mode) {
float tmp = 0.0f;
/*luma[i] = pow((1.0f - luma[i] / 4096.0f), 2.0f)*/
float luma[DRC_CURVE_LEN] = {1.0f, 0.8789f, 0.7656f, 0.6602f, 0.5625f, 0.4727f,
0.3906f, 0.3164f, 0.2500f, 0.1914f, 0.1406f, 0.0977f,
0.0625f, 0.0352f, 0.0156f, 0.0039f, 0.0f };
float DrcGain = out->dyn.preProc.sw_drcT_toneGain_maxLimit;
float alpha = out->dyn.preProc.sw_drcT_toneCurveK_coeff;
for (int i = 0; i < DRC_CURVE_LEN; ++i) {
tmp = 1 - alpha * luma[i];
if (pDrcCtx->blc_ob_enable)
tmp = 1024.0f * pow(DrcGain * pDrcCtx->isp_ob_predgain, tmp) *
pow(pDrcCtx->isp_ob_predgain, -alpha * luma[i]);
else
tmp = 1024.0f * pow(DrcGain, tmp);
out->dyn.preProc.hw_drcT_luma2ToneGain_val[i] = (unsigned short)(tmp);
}
}
if (pDrcCtx->drc_attrib->opMode == RK_AIQ_OP_MODE_AUTO)
pDrcCtx->CurrData.dynParams = out->dyn;
LOG1_ATMO("%s:exit!\n", __FUNCTION__);
return XCAM_RETURN_NO_ERROR;
}
void DrcAutoProcessing(drc_param_t* out, drc_param_auto_t* paut, float iso) {
LOG1_ATMO("%s:enter!\n", __FUNCTION__);
int i = 0;
int iso_low = 0, iso_high = 0, ilow = 0, ihigh = 0;
float ratio = 0.0f;
uint16_t uratio;
pre_interp(iso, NULL, 0, ilow, ihigh, ratio);
uratio = ratio * (1 << RATIO_FIXBIT);
// get preProc
// get sw_drcT_toneGain_maxLimit
out->dyn.preProc.sw_drcT_toneGain_maxLimit =
interpolation_f32(paut->dyn[ilow].preProc.sw_drcT_toneGain_maxLimit,
paut->dyn[ihigh].preProc.sw_drcT_toneGain_maxLimit, ratio);
// get sw_drcT_toneCurveK_coeff
out->dyn.preProc.sw_drcT_toneCurveK_coeff =
interpolation_f32(paut->dyn[ilow].preProc.sw_drcT_toneCurveK_coeff,
paut->dyn[ihigh].preProc.sw_drcT_toneCurveK_coeff, ratio);
// get sw_drcT_toneCurve_mode
out->dyn.preProc.sw_drcT_toneCurve_mode =
paut->dyn[ilow].preProc.sw_drcT_toneCurve_mode;
// get hw_drcT_toneCurveIdx_scale
out->dyn.preProc.hw_drcT_toneCurveIdx_scale =
interpolation_f32(paut->dyn[ilow].preProc.hw_drcT_toneCurveIdx_scale,
paut->dyn[ihigh].preProc.hw_drcT_toneCurveIdx_scale, ratio);
// get hw_drcT_lpfSoftThd_thred
out->dyn.preProc.hw_drcT_lpfSoftThd_thred =
interpolation_f32(paut->dyn[ilow].preProc.hw_drcT_lpfSoftThd_thred,
paut->dyn[ihigh].preProc.hw_drcT_lpfSoftThd_thred, ratio);
// get hw_drcT_luma2ToneGain_val
for (int i = 0; i < DRC_CURVE_LEN; i++)
out->dyn.preProc.hw_drcT_luma2ToneGain_val[i] =
interpolation_f32(paut->dyn[ilow].preProc.hw_drcT_luma2ToneGain_val[i],
paut->dyn[ihigh].preProc.hw_drcT_luma2ToneGain_val[i], ratio);
// get bifilt_filter
// get hw_drcT_bifiltOut_alpha
out->dyn.bifilt_filter.hw_drcT_bifiltOut_alpha =
interpolation_u8(paut->dyn[ilow].bifilt_filter.hw_drcT_bifiltOut_alpha,
paut->dyn[ihigh].bifilt_filter.hw_drcT_bifiltOut_alpha, uratio);
// get hw_drcT_softThd_en
out->dyn.bifilt_filter.hw_drcT_softThd_en =
paut->dyn[ilow].bifilt_filter.hw_drcT_softThd_en;
// get hw_drcT_softThd_thred
out->dyn.bifilt_filter.hw_drcT_softThd_thred =
interpolation_f32(paut->dyn[ilow].bifilt_filter.hw_drcT_softThd_thred,
paut->dyn[ihigh].bifilt_filter.hw_drcT_softThd_thred, uratio);
// get hw_drcT_centerPixel_wgt
out->dyn.bifilt_filter.hw_drcT_centerPixel_wgt =
interpolation_u8(paut->dyn[ilow].bifilt_filter.hw_drcT_centerPixel_wgt,
paut->dyn[ihigh].bifilt_filter.hw_drcT_centerPixel_wgt, uratio);
// get hw_drcT_midWgt_alpha
out->dyn.bifilt_filter.hw_drcT_midWgt_alpha =
interpolation_u8(paut->dyn[ilow].bifilt_filter.hw_drcT_midWgt_alpha,
paut->dyn[ihigh].bifilt_filter.hw_drcT_midWgt_alpha, uratio);
// get hw_drcT_rgeWgt_negOff
out->dyn.bifilt_filter.hw_drcT_rgeWgt_negOff =
interpolation_u8(paut->dyn[ilow].bifilt_filter.hw_drcT_rgeWgt_negOff,
paut->dyn[ihigh].bifilt_filter.hw_drcT_rgeWgt_negOff, uratio);
// get hw_drcT_midRgeSgm_val
out->dyn.bifilt_filter.hw_drcT_midRgeSgm_val =
interpolation_f32(paut->dyn[ilow].bifilt_filter.hw_drcT_midRgeSgm_val,
paut->dyn[ihigh].bifilt_filter.hw_drcT_midRgeSgm_val, uratio);
// get hw_drcT_loRgeSgm_val
out->dyn.bifilt_filter.hw_drcT_loRgeSgm_val =
interpolation_f32(paut->dyn[ilow].bifilt_filter.hw_drcT_loRgeSgm_val,
paut->dyn[ihigh].bifilt_filter.hw_drcT_loRgeSgm_val, uratio);
// get bifilt_guideDiff
// get hw_drc_thumb_maxLimit
out->dyn.bifilt_guideDiff.hw_drcT_guideDiffLmt_en =
interpolation_bool(paut->dyn[ilow].bifilt_guideDiff.hw_drcT_guideDiffLmt_en,
paut->dyn[ihigh].bifilt_guideDiff.hw_drcT_guideDiffLmt_en, uratio);
out->dyn.bifilt_guideDiff.hw_drcT_guideLuma_maxLimit =
interpolation_f32(paut->dyn[ilow].bifilt_guideDiff.hw_drcT_guideLuma_maxLimit,
paut->dyn[ihigh].bifilt_guideDiff.hw_drcT_guideLuma_maxLimit, uratio);
// get hw_drcT_maxLutIdx_scale
out->dyn.bifilt_guideDiff.hw_drcT_maxLutIdx_scale =
interpolation_f32(paut->dyn[ilow].bifilt_guideDiff.hw_drcT_maxLutIdx_scale,
paut->dyn[ihigh].bifilt_guideDiff.hw_drcT_maxLutIdx_scale, uratio);
// get hw_drcT_guideDiff_minLimit
out->dyn.bifilt_guideDiff.hw_drcT_guideDiff_minLimit =
interpolation_f32(paut->dyn[ilow].bifilt_guideDiff.hw_drcT_guideDiff_minLimit,
paut->dyn[ihigh].bifilt_guideDiff.hw_drcT_guideDiff_minLimit, uratio);
// get sw_drcT_gdDiffMaxLut_mode
out->dyn.bifilt_guideDiff.sw_drcT_gdDiffMaxLut_mode =
paut->dyn[ilow].bifilt_guideDiff.sw_drcT_gdDiffMaxLut_mode;
// get hw_drcT_gdLuma2DiffMax_lut
for (int i = 0; i < DRC_CURVE_LEN; i++)
out->dyn.bifilt_guideDiff.hw_drcT_gdLuma2DiffMax_lut[i] =
interpolation_f32(paut->dyn[ilow].bifilt_guideDiff.hw_drcT_gdLuma2DiffMax_lut[i],
paut->dyn[ihigh].bifilt_guideDiff.hw_drcT_gdLuma2DiffMax_lut[i], uratio);
// get sw_drc_thumbThred_minLimit
out->dyn.bifilt_guideDiff.sw_drcT_maxLutCreate_minLimit =
interpolation_f32(paut->dyn[ilow].bifilt_guideDiff.sw_drcT_maxLutCreate_minLimit,
paut->dyn[ihigh].bifilt_guideDiff.sw_drcT_maxLutCreate_minLimit, uratio);
// get sw_drc_thumbThred_maxLimit
out->dyn.bifilt_guideDiff.sw_drcT_maxLutCreate_maxLimit =
interpolation_f32(paut->dyn[ilow].bifilt_guideDiff.sw_drcT_maxLutCreate_maxLimit,
paut->dyn[ihigh].bifilt_guideDiff.sw_drcT_maxLutCreate_maxLimit, uratio);
// get sw_drc_thumbThredCurve_slope
out->dyn.bifilt_guideDiff.sw_drcT_maxLutCreate_slope =
interpolation_f32(paut->dyn[ilow].bifilt_guideDiff.sw_drcT_maxLutCreate_slope,
paut->dyn[ihigh].bifilt_guideDiff.sw_drcT_maxLutCreate_slope, uratio);
// get sw_drc_thumbThredCurve_offset
out->dyn.bifilt_guideDiff.sw_drcT_maxLutCreate_offset =
interpolation_f32(paut->dyn[ilow].bifilt_guideDiff.sw_drcT_maxLutCreate_offset,
paut->dyn[ihigh].bifilt_guideDiff.sw_drcT_maxLutCreate_offset, uratio);
// get drcProc
// get hw_drcT_loDetail_strg
out->dyn.drcProc.hw_drcT_loDetail_strg =
interpolation_f32(paut->dyn[ilow].drcProc.hw_drcT_loDetail_strg,
paut->dyn[ihigh].drcProc.hw_drcT_loDetail_strg, uratio);
// get hw_drcT_drcStrg_alpha
out->dyn.drcProc.hw_drcT_drcStrg_alpha =
interpolation_f32(paut->dyn[ilow].drcProc.hw_drcT_drcStrg_alpha,
paut->dyn[ihigh].drcProc.hw_drcT_drcStrg_alpha, uratio);
// get hw_drcT_drcStrgLutLuma_scale
out->dyn.drcProc.hw_drcT_drcStrgLutLuma_scale =
interpolation_f32(paut->dyn[ilow].drcProc.hw_drcT_drcStrgLutLuma_scale,
paut->dyn[ihigh].drcProc.hw_drcT_drcStrgLutLuma_scale, uratio);
// get sw_drcT_drcStrgLut_mode
out->dyn.drcProc.sw_drcT_drcStrgLut_mode =
paut->dyn[ilow].drcProc.sw_drcT_drcStrgLut_mode; //TODO
// get hw_drc_luma2compsGainScale_val
for (int i = 0; i < DRC_CURVE_LEN; i++)
out->dyn.drcProc.hw_drcT_luma2DrcStrg_val[i] =
interpolation_f32(paut->dyn[ilow].drcProc.hw_drcT_luma2DrcStrg_val[i],
paut->dyn[ihigh].drcProc.hw_drcT_luma2DrcStrg_val[i], uratio);
// get sw_drcT_drcCurve_mode
out->dyn.drcProc.sw_drcT_drcCurve_mode =
paut->dyn[ilow].drcProc.sw_drcT_drcCurve_mode;
// get sw_drcT_drcGainLimit_mode
out->dyn.drcProc.sw_drcT_drcGainLimit_mode =
paut->dyn[ilow].drcProc.sw_drcT_drcGainLimit_mode;
LOG1_ATMO("%s:exit!\n", __FUNCTION__);
}
bool DrcDamping(drc_param_t* out, CurrData_t* pCurrData, int FrameID) {
LOG1_ATMO("%s:Enter!\n", __FUNCTION__);
bool isDampStable = false;
// if (FrameID > 2) {
// bool isDampStable_DrcGain = false, isDampStable_Alpha = false,
// isDampStable_LocalAutoWeitEn = false, isDampStable_LocalWeit = false,
// isDampStable_LocalAutoWeit = false, isDampStable_GlobalContrast = false,
// isDampStable_LoLitContrast = false;
// // isDampStable_DrcGain
// if ((out->dyn.preProc.sw_drcT_toneGain_maxLimit -
// pCurrData->dynParams.preProc
// .sw_drcT_toneGain_maxLimit) <= FLT_EPSILON &&
// (out->dyn.preProc.sw_drcT_toneGain_maxLimit -
// pCurrData->dynParams.preProc
// .sw_drcT_toneGain_maxLimit) >= -FLT_EPSILON) {
// isDampStable_DrcGain = true;
// } else {
// out->dyn.preProc.sw_drcT_toneGain_maxLimit =
// out->sta.sw_drc_damp_coef * out->dyn.preProc.sw_drcT_toneGain_maxLimit +
// (1.0f - out->sta.sw_drc_damp_coef) * out->dyn.preProc.sw_drcT_toneGain_maxLimit;
// isDampStable_DrcGain = false;
// }
// // isDampStable_Alpha
// if ((out->dyn.preProc.hw_drcT_toneCurveIdx_scale -
// pCurrData->dynParams.preProc.hw_drcT_toneCurveIdx_scale) <= FLT_EPSILON &&
// (out->dyn.preProc.hw_drcT_toneCurveIdx_scale -
// pCurrData->dynParams.preProc.hw_drcT_toneCurveIdx_scale) >= -FLT_EPSILON) {
// isDampStable_Alpha = true;
// } else {
// out->dyn.preProc.hw_drcT_toneCurveIdx_scale =
// out->sta.sw_drc_damp_coef * out->dyn.preProc.hw_drcT_toneCurveIdx_scale +
// (1.0f - out->sta.sw_drc_damp_coef)
// * pCurrData->dynParams.preProc.hw_drcT_toneCurveIdx_scale;
// isDampStable_Alpha = false;
// }
// // isDampStable_LocalWeit
// if (out->dyn.bifilt_filter.hw_drcT_bifiltOut_alpha ==
// pCurrData->dynParams.bifilt_filter.hw_drcT_bifiltOut_alpha) {
// isDampStable_LocalWeit = true;
// } else {
// out->dyn.bifilt_filter.hw_drcT_bifiltOut_alpha =
// out->sta.sw_drc_damp_coef * out->dyn.bifilt_filter.hw_drcT_bifiltOut_alpha +
// (1.0f - out->sta.sw_drc_damp_coef) * pCurrData->dynParams.bifilt_filter.hw_drcT_bifiltOut_alpha;
// isDampStable_LocalWeit = false;
// }
// // isDampStable_LocalAutoWeit
// if (out->dyn.bifilt_filter.hw_adrc_softThd_thred ==
// pCurrData->dynParams.bifilt_filter.hw_adrc_softThd_thred) {
// isDampStable_LocalAutoWeit = true;
// } else {
// out->dyn.bifilt_filter.hw_adrc_softThd_thred =
// out->sta.sw_drc_damp_coef * out->dyn.bifilt_filter.hw_adrc_softThd_thred +
// (1.0f - out->sta.sw_drc_damp_coef) * pCurrData->dynParams.bifilt_filter.hw_adrc_softThd_thred;
// isDampStable_LocalAutoWeit = false;
// }
// // isDampStable_LocalAutoWeitEn
// if (out->dyn.bifilt_filter.hw_adrc_softThd_en ==
// pCurrData->dynParams.bifilt_filter.hw_adrc_softThd_en) {
// isDampStable_LocalAutoWeitEn = true;
// } else {
// out->dyn.bifilt_filter.hw_adrc_softThd_en =
// out->sta.sw_drc_damp_coef * out->dyn.bifilt_filter.hw_adrc_softThd_en +
// (1.0f - out->sta.sw_drc_damp_coef) * pCurrData->dynParams.bifilt_filter.hw_adrc_softThd_en;
// isDampStable_LocalAutoWeitEn = false;
// }
// // isDampStable_GlobalContrast
// if (out->dyn.drcProc.hw_drcT_drcStrg_alpha ==
// pCurrData->dynParams.drcProc.hw_drcT_drcStrg_alpha) {
// isDampStable_GlobalContrast = true;
// } else {
// out->dyn.drcProc.hw_drcT_drcStrg_alpha =
// out->sta.sw_drc_damp_coef * out->dyn.drcProc.hw_drcT_drcStrg_alpha +
// (1.0f - out->sta.sw_drc_damp_coef) * pCurrData->dynParams.drcProc.hw_drcT_drcStrg_alpha;
// isDampStable_GlobalContrast = false;
// }
// // isDampStable_LoLitContrast
// if (out->dyn.drcProc.hw_drcT_loDetail_strg ==
// pCurrData->dynParams.drcProc.hw_drcT_loDetail_strg) {
// isDampStable_LoLitContrast = true;
// } else {
// out->dyn.drcProc.hw_drcT_loDetail_strg =
// out->sta.sw_drc_damp_coef * out->dyn.drcProc.hw_drcT_loDetail_strg +
// (1.0f - out->sta.sw_drc_damp_coef) * pCurrData->dynParams.drcProc.hw_drcT_loDetail_strg;
// isDampStable_LoLitContrast = false;
// }
// isDampStable = isDampStable_DrcGain && isDampStable_Alpha && isDampStable_LocalAutoWeitEn &&
// isDampStable_LocalWeit && isDampStable_LocalAutoWeit &&
// isDampStable_GlobalContrast && isDampStable_LoLitContrast;
// } else
// isDampStable = false;
// LOG1_ATMO("%s:Eixt!\n", __FUNCTION__);
return isDampStable;
}
void DrcExpoParaProcessing(DrcContext_t* pDrcCtx, drc_param_t* out, int iso) {
LOG1_ATMO("%s:enter!\n", __FUNCTION__);
// get sw_drc_compres_scl
float drc_gain = 1.0f;
if (pDrcCtx->FrameNumber == LINEAR_NUM && pDrcCtx->blc_ob_enable)
drc_gain = out->dyn.preProc.sw_drcT_toneGain_maxLimit * pDrcCtx->isp_ob_predgain;
else
drc_gain = out->dyn.preProc.sw_drcT_toneGain_maxLimit;
float log_ratio2 = log(pDrcCtx->NextData.AEData.L2S_Ratio * drc_gain) / log(2.0f) + 12.0f;
float offsetbits_int = CLIP(pDrcCtx->hw_transCfg_transOfDrc_offset, 0, 15);
unsigned char cmps_fixbit_mode = (pDrcCtx->hw_transCfg_trans_mode == trans_lgi3f9_mode ?
FUNCTION_ENABLE : FUNCTION_DISABLE);
LOGD_ATMO("pDrcCtx->hw_transCfg_transOfDrc_offset %d", pDrcCtx->hw_transCfg_transOfDrc_offset);
int cmps_fix_bit = 8 + cmps_fixbit_mode;
float offsetbits = offsetbits_int * (1 << cmps_fix_bit);
float hdrbits = log_ratio2 * (1 << cmps_fix_bit);
float hdrvalidbits = hdrbits - offsetbits;
out->dyn.preProc.hw_drcT_drcCurveLuma_scale = (12.0f * (1 << (cmps_fix_bit + 11))) / hdrvalidbits;
int iso_low = 0, iso_high = 0, ilow = 0, ihigh = 0;
float ratio = 0.0f;
uint16_t uratio;
pre_interp(iso, NULL, 0, ilow, ihigh, ratio);
uratio = ratio * (1 << RATIO_FIXBIT);
// get hw_drc_comps_gain_minLimit
drc_param_auto_t* paut = &pDrcCtx->drc_attrib->stAuto;
if (out->dyn.drcProc.sw_drcT_drcGainLimit_mode == drc_drcGainLmt_auto_mode) {
out->dyn.drcProc.hw_drcT_drcGain_minLimit =
1.0f / (pDrcCtx->NextData.AEData.L2S_Ratio * drc_gain);
}
else {
out->dyn.drcProc.hw_drcT_drcGain_minLimit =
interpolation_f32(paut->dyn[ilow].drcProc.hw_drcT_drcGain_minLimit,
paut->dyn[ihigh].drcProc.hw_drcT_drcGain_minLimit, uratio);
}
// // clip hw_drc_compsGain_minLimit
// if (pDrcCtx->NextData.AEData.LongFrmMode)
// out->dyn.drcProc.hw_drcT_drcGain_minLimit = 1;
// get sw_drc_compres_y
if (out->dyn.drcProc.sw_drcT_drcCurve_mode == drc_vendorDefault_mode) {
float luma2[DRC_CURVE_LEN] = {0.0f, 1024.0f, 2048.0f, 3072.0f, 4096.0f, 5120.0f,
6144.0f, 7168.0f, 8192.0f, 10240.0f, 12288.0f, 14336.0f,
16384.0f, 18432.0f, 20480.0f, 22528.0f, 24576.0f};
float dstbits = (float)(ISP_RAW_BIT << cmps_fix_bit);
float validbits = dstbits - offsetbits;
float curveparam = (float)(validbits - 0.0f) / (hdrvalidbits - validbits + 0.0156f);
float curveparam2 = validbits * (1.0f + curveparam);
float curveparam3 = hdrvalidbits * curveparam;
for (int i = 0; i < DRC_CURVE_LEN; ++i) {
float tmp = luma2[i] * hdrvalidbits / 24576.0f;
float curveTable = tmp * curveparam2 / (tmp + curveparam3);
out->dyn.drcProc.hw_drcT_hdr2Sdr_curve[i] =
((unsigned short)(curveTable)) >> cmps_fixbit_mode;
}
} else if (out->dyn.drcProc.sw_drcT_drcCurve_mode == drc_usrConfig_mode) {
for (int i = 0; i < DRC_CURVE_LEN; ++i)
out->dyn.drcProc.hw_drcT_hdr2Sdr_curve[i] =
interpolation_f32(paut->dyn[ilow].drcProc.hw_drcT_hdr2Sdr_curve[i],
paut->dyn[ihigh].drcProc.hw_drcT_hdr2Sdr_curve[i], uratio);
}
}
#endif
XCamReturn
algo_drc_SetAttrib
(
RkAiqAlgoContext* ctx,
drc_api_attrib_t *attr
) {
if(ctx == NULL || attr == NULL) {
LOGE_ATMO("%s(%d): null pointer\n", __FUNCTION__, __LINE__);
return XCAM_RETURN_ERROR_PARAM;
}
DrcContext_t* pDrcCtx = (DrcContext_t*)ctx;
drc_api_attrib_t* drc_attrib = pDrcCtx->drc_attrib;
if (attr->opMode != RK_AIQ_OP_MODE_AUTO) {
LOGE_ATMO("not auto mode: %d", attr->opMode);
return XCAM_RETURN_ERROR_PARAM;
}
drc_attrib->opMode = attr->opMode;
drc_attrib->en = attr->en;
drc_attrib->bypass = attr->bypass;
if (attr->opMode == RK_AIQ_OP_MODE_AUTO)
drc_attrib->stAuto = attr->stAuto;
else if (attr->opMode == RK_AIQ_OP_MODE_MANUAL)
drc_attrib->stMan = attr->stMan;
else {
LOGW_ATMO("wrong mode: %d\n", attr->opMode);
}
pDrcCtx->isReCal_ = true;
return XCAM_RETURN_NO_ERROR;
}
XCamReturn
algo_drc_GetAttrib
(
RkAiqAlgoContext* ctx,
drc_api_attrib_t* attr
)
{
if(ctx == NULL || attr == NULL) {
LOGE_ATMO("%s(%d): null pointer\n", __FUNCTION__, __LINE__);
return XCAM_RETURN_ERROR_PARAM;
}
DrcContext_t* pDrcCtx = (DrcContext_t*)ctx;
drc_api_attrib_t* drc_attrib = pDrcCtx->drc_attrib;
#if 0
if (drc_attrib->opMode != RK_AIQ_OP_MODE_AUTO) {
LOGE_ATMO("not auto mode: %d", drc_attrib->opMode);
return XCAM_RETURN_ERROR_PARAM;
}
#endif
attr->opMode = drc_attrib->opMode;
attr->en = drc_attrib->en;
attr->bypass = drc_attrib->bypass;
memcpy(&attr->stAuto, &drc_attrib->stAuto, sizeof(drc_param_auto_t));
return XCAM_RETURN_NO_ERROR;
}
#define RKISP_ALGO_DRC_VERSION "v0.1.0"
#define RKISP_ALGO_DRC_VENDOR "Rockchip"
#define RKISP_ALGO_DRC_DESCRIPTION "Rockchip drc algo for ISP2.0"
RkAiqAlgoDescription g_RkIspAlgoDescDrc = {
.common = {
.version = RKISP_ALGO_DRC_VERSION,
.vendor = RKISP_ALGO_DRC_VENDOR,
.description = RKISP_ALGO_DRC_DESCRIPTION,
.type = RK_AIQ_ALGO_TYPE_ADRC,
.id = 0,
.create_context = create_context,
.destroy_context = destroy_context,
},
.prepare = prepare,
.pre_process = NULL,
.processing = processing,
.post_process = NULL,
};
//RKAIQ_END_DECLARE