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.

372 lines
15 KiB

#include "common/rk-aiisp-config.h"
#include "common/rk-isp35-config.h"
#define AIBNR_PYRAMID_LAYER_NUM_4 4
#define AIBNR_PREV_LUT_BIT_5 5
#define AIBNR_POST_LUT_BIT_5 5
#define AIBNR_SIGMA_LUT_ROW_BIT_3 3
#define AIBNR_SIGMA_LUT_COL_BIT_3 3
#define AIBNR_RAW_DATA_BIT_16 16
#define AIBNR_NAR_MAP_BIT_7 7
#define AIBNR_GAIN_DOWN_SCALE_ROW_2 2
#define AIBNR_GAIN_DOWN_SCALE_COL_8 8
#define AIBNR_NPU_FEATURE_BIT_10 10
#define AIBNR_PREV_LUT_LEN_33 ((1 << AIBNR_PREV_LUT_BIT_5) + 1)
#define AIBNR_POST_LUT_LEN_33 ((1 << AIBNR_POST_LUT_BIT_5) + 1)
#define AIBNR_SIGMA_LUT_ROW_LEN_9 ((1<<AIBNR_SIGMA_LUT_ROW_BIT_3) + 1)
#define AIBNR_SIGMA_LUT_COL_LEN_9 ((1<<AIBNR_SIGMA_LUT_COL_BIT_3) + 1)
#define AIBNR_RAW_DATA_MAX_65535 ((1 << AIBNR_RAW_DATA_BIT_16) - 1)
#define AIBNR_NPU_FEATURE_MAX_1023 ((1 << AIBNR_NPU_FEATURE_BIT_10) - 1)
#define AIBNR_NOISE_LIMIT_RANGE_32767 32767
static float nonLinear(float x, int flag, float r, float scale)
{
float R2 = (1 + r)*(1 + r) + r * r;
float y = 0;
if (flag == 0)
{
x = CLIP(x, 0, 1);
float X2 = (ABS(x) - (1 + r))*(ABS(x) - (1 + r));
y = (sqrt(R2 - X2) - r) * scale;
}
else
{
x = CLIP(x / scale, 0, 1);
float X2 = (ABS(x) + r)*(ABS(x) + r);
y = (r + 1) - sqrt(R2 - X2);
}
return y;
}
float Linear(float x, float scale, int flag)
{
float y = 0;
if (flag == 0)
{
y = x * scale;
y = CLIP(y, 0, 1);
}
else
{
y = x / scale;
y = CLIP(y, 0, 1);
}
return y;
}
float logTransf(float x, int flag, float offset)
{
float y = 0;
if (flag == 0)
{
x = x * (1 << 16);
y = log2(x + offset) - log2(offset);
y = y * (1 << 12);
y = y / (1 << 16);
}
else
{
x = x * (1 << 16);
x = x / (1 << 12);
y = x + log2(offset);
y = pow(2, y) - offset;
y = y / (1 << 16);
}
return y;
}
static void rk_aiq_aibnr_params_print(struct isp35_ai_cfg* ai_cfg)
{
int i;
LOGD_AIBNR("aipre:");
LOGD_AIBNR("aiisp_raw12_msb = 0x%x", ai_cfg->aiisp_raw12_msb);
LOGD_AIBNR("aiisp_gain_mode = 0x%x", ai_cfg->aiisp_gain_mode);
LOGD_AIBNR("aiisp_curve_en = 0x%x", ai_cfg->aiisp_curve_en);
LOGD_AIBNR("aipre_iir_en = 0x%x", ai_cfg->aipre_iir_en);
LOGD_AIBNR("aipre_iir2ddr_en = 0x%x", ai_cfg->aipre_iir2ddr_en);
LOGD_AIBNR("aipre_gain_en = 0x%x", ai_cfg->aipre_gain_en);
LOGD_AIBNR("aipre_gain2ddr_en = 0x%x", ai_cfg->aipre_iir_en);
LOGD_AIBNR("aipre_luma2gain_dis = 0x%x", ai_cfg->aipre_luma2gain_dis);
LOGD_AIBNR("aipre_nl_ddr_mode = 0x%x", ai_cfg->aipre_nl_ddr_mode);
LOGD_AIBNR("aipre_yraw_sel = 0x%x", ai_cfg->aipre_yraw_sel);
LOGD_AIBNR("aipre_gain_bypass = 0x%x", ai_cfg->aipre_gain_bypass);
LOGD_AIBNR("aipre_gain_mode = 0x%x", ai_cfg->aipre_gain_mode);
LOGD_AIBNR("aipre_narmap_inv = 0x%x", ai_cfg->aipre_narmap_inv);
for (i = 0; i < ISP35_AI_SIGMA_NUM; i++) {
LOGD_AIBNR("aiisp_sigma_y[%d] = 0x%x", i, ai_cfg->aiisp_sigma_y[i]);
}
LOGD_AIBNR("aipre_scale = 0x%x", ai_cfg->aipre_scale);
LOGD_AIBNR("aipre_zp = 0x%x", ai_cfg->aipre_zp);
LOGD_AIBNR("aipre_black_lvl = 0x%x", ai_cfg->aipre_black_lvl);
LOGD_AIBNR("aipre_gain_alpha = 0x%x", ai_cfg->aipre_gain_alpha);
LOGD_AIBNR("aipre_global_gain = 0x%x", ai_cfg->aipre_global_gain);
LOGD_AIBNR("aipre_gain_ratio = 0x%x", ai_cfg->aipre_gain_ratio);
for (i = 0; i < ISP35_AI_SIGMA_NUM; i++) {
LOGD_AIBNR("aipre_sigma_y[%d] = 0x%x", i, ai_cfg->aipre_sigma_y[i]);
}
LOGD_AIBNR("aipre_noise_mot_offset = 0x%x", ai_cfg->aipre_noise_mot_offset);
LOGD_AIBNR("aipre_noise_mot_gain = 0x%x", ai_cfg->aipre_noise_mot_gain);
LOGD_AIBNR("aipre_noise_luma_offset = 0x%x", ai_cfg->aipre_noise_luma_offset);
LOGD_AIBNR("aipre_noise_luma_gain = 0x%x", ai_cfg->aipre_noise_luma_gain);
LOGD_AIBNR("aipre_noise_luma_clip = 0x%x", ai_cfg->aipre_noise_luma_clip);
LOGD_AIBNR("aipre_noise_luma_static = 0x%x", ai_cfg->aipre_noise_luma_static);
LOGD_AIBNR("aipre_nar_manual = 0x%x", ai_cfg->aipre_nar_manual);
LOGD_AIBNR("aipre_nar_manual_alpha = 0x%x", ai_cfg->aipre_nar_manual_alpha);
LOGD_AIBNR("pyr_yraw_mode = 0x%x", ai_cfg->pyr_yraw_mode);
LOGD_AIBNR("pyr_sigma_en = 0x%x", ai_cfg->pyr_sigma_en);
LOGD_AIBNR("pyr_yraw_sel = 0x%x", ai_cfg->pyr_yraw_sel);
LOGD_AIBNR("pyr_gain_leftshift = 0x%x", ai_cfg->pyr_gain_leftshift);
LOGD_AIBNR("pyr_blacklvl_sig = 0x%x", ai_cfg->pyr_blacklvl_sig);
for (i = 0; i < ISP35_VPSL_SIGMA_NUM; i++) {
LOGD_AIBNR("pyr_sigma_y[%d] = 0x%x", i, ai_cfg->pyr_sigma_y[i]);
}
}
void rk_aiq_aibnr_params_cvt(void* attr, isp_params_t* isp_params, common_cvt_info_t *cvtinfo, bool bypass)
{
struct isp35_ai_cfg* ai_cfg = &isp_params->isp_cfg->others.ai_cfg;
RkAiqAibnrModelInfo_t *pAibnrModelInfo = &cvtinfo->aibnrModelInfo;
int i;
rk_aiq_isp_aibnr_params_t *isp_aibnr_param = (rk_aiq_isp_aibnr_params_t *) attr;
aibnr_param_t *aibnr_param = &isp_aibnr_param->aibnr_param;
aibnr_params_static_t* psta = &aibnr_param->sta;
aibnr_param_calib_t *calib = &aibnr_param->dyn.calib;
aibnr_param_tunning_t *tunning = &aibnr_param->dyn.tunning;
if (!cvtinfo->use_aiisp) {
memset(ai_cfg, 0, sizeof(*ai_cfg));
LOGD_AIBNR("aiisp is disabled");
return;
}
isp_aibnr_param->is_bypass = bypass;
isp_aibnr_param->is_hdr = (cvtinfo->frameNum > 1) ? true : false;
float hdrLS_ratio = cvtinfo->L2S_Ratio;
float preDgain = cvtinfo->preDGain_drc;
int btnrCfg_pixDomain_mode = cvtinfo->btnrCfg_pixDomain_mode;
int hw_btnrCfg_trans_mode = cvtinfo->btnrCfg_trans_mode;
int hw_btnrCfg_trans_offset = cvtinfo->btnrCfg_trans_offset;
float sw_aiBnrC_blkPrev_offset = cvtinfo->isp_ob_offset1 + calib->sw_aiBnrC_blkPrev_offset;
float sw_aiBnrC_blkPost_offset = cvtinfo->isp_ob_offset1 + calib->sw_aiBnrC_blkPost_offset;
if (preDgain < 1.0)
preDgain = 1.0;
sw_aiBnrC_blkPrev_offset = CLIP(sw_aiBnrC_blkPrev_offset, 0, 511);
sw_aiBnrC_blkPost_offset = CLIP(sw_aiBnrC_blkPost_offset, 0, 511);
LOGD_AIBNR("%s: frameNum %d, L2S_Ratio %f, preDGain %f, pixDomain_mode %d, trans_mode %d, trans_offset %d, isp_ob_offset %d, isp_ob_offset1 %d, sw_aiBnrC_blkPrev_offset %f, sw_aiBnrC_blkPost_offset %f",
__func__,
cvtinfo->frameNum, cvtinfo->L2S_Ratio, preDgain, cvtinfo->btnrCfg_pixDomain_mode,
cvtinfo->btnrCfg_trans_mode, cvtinfo->btnrCfg_trans_offset,
cvtinfo->isp_ob_offset, cvtinfo->isp_ob_offset1, sw_aiBnrC_blkPrev_offset, sw_aiBnrC_blkPost_offset);
if (cvtinfo->frameNum > 1) {
if (btnrCfg_pixDomain_mode != btnr_pixLog2Domain_mode) {
LOGE_AIBNR("btnrCfg_pixDomain_mode(%d) is not log2Domain in hdr mode", btnrCfg_pixDomain_mode);
}
if (hw_btnrCfg_trans_mode != btnr_pixInBw20b_mode) {
LOGE_AIBNR("hw_btnrCfg_trans_mode(%d) is not btnr_pixInBw20b_mode in hdr mode", hw_btnrCfg_trans_mode);
}
} else {
hdrLS_ratio = 1;
if (preDgain > 1.0) {
if (btnrCfg_pixDomain_mode != btnr_pixLog2Domain_mode) {
LOGE_AIBNR("btnrCfg_pixDomain_mode(%d) is not log2Domain when preDgain(%f) > 1", btnrCfg_pixDomain_mode, preDgain);
}
}
}
ai_cfg->aiisp_raw12_msb = 1;
ai_cfg->aiisp_gain_mode = 1;//(cvtinfo->frameNum > 1) ? 0 : 1;
ai_cfg->aipre_iir_en = 1;
ai_cfg->aipre_iir2ddr_en = 1;
ai_cfg->aipre_gain_en = 1;
ai_cfg->aipre_gain2ddr_en = 1;
ai_cfg->aipre_yraw_sel = 1;
ai_cfg->aipre_nl_ddr_mode = 1;
ai_cfg->aipre_gain_bypass = 0;
ai_cfg->aipre_gain_mode = 0;
ai_cfg->aipre_luma2gain_dis = (cvtinfo->rawWidth % 8 != 0) ? 1 : 0;
/* VPSL_PYR_CTRL */
ai_cfg->pyr_yraw_mode = 1;
ai_cfg->pyr_sigma_en = 1;
ai_cfg->pyr_yraw_sel = 1;
ai_cfg->aiisp_curve_en = 0;
for (i = 0; i < 33; i++)
ai_cfg->aiisp_sigma_y[i] = 0; // 12bit to 12bit convertion curve
float logMax = 0;
float logScale = 1;
float log_offset = hw_btnrCfg_trans_offset;
float nonlinear_scale = tunning->sw_aiBnrT_nonLinear_scale;
float nonlinear_ratio = tunning->sw_aiBnrT_nonLinear_ratio;
float nonlinear_adjust = tunning->sw_aiBnrT_nonLinear_adjust;
if (btnrCfg_pixDomain_mode == btnr_pixLog2Domain_mode) {
logMax = (log2(log_offset + (1 << 12) * hdrLS_ratio * preDgain) - log2(log_offset)) * (1 << 12) / (1 << 16);
logScale = nonlinear_scale / logMax;
ai_cfg->aipre_black_lvl = (log2(log_offset + sw_aiBnrC_blkPrev_offset) - log2(log_offset)) * (1 << 12);
ai_cfg->pyr_blacklvl_sig = ai_cfg->aipre_black_lvl / 256;
isp_aibnr_param->prev_blacklvl = ai_cfg->aipre_black_lvl;
isp_aibnr_param->post_blacklvl = (log2(log_offset + sw_aiBnrC_blkPost_offset) - log2(log_offset)) * (1 << 12);
} else {
ai_cfg->aipre_black_lvl = sw_aiBnrC_blkPrev_offset * (1 << 4);
ai_cfg->pyr_blacklvl_sig = sw_aiBnrC_blkPrev_offset * (1 << 4) / 256;
isp_aibnr_param->prev_blacklvl = ai_cfg->aipre_black_lvl;
isp_aibnr_param->post_blacklvl = sw_aiBnrC_blkPost_offset * (1 << 4);
}
ai_cfg->aipre_black_lvl = ai_cfg->aipre_black_lvl >> 4;
ai_cfg->aipre_gain_ratio = tunning->sw_aiBnrT_noiseAdd_ratio * (1 << AIBNR_NAR_MAP_BIT_7) * 255;
ai_cfg->aipre_noise_mot_offset = sqrt(1.0 / tunning->sw_aiBnrT_noiseAddMot_offset) * 255.0;
ai_cfg->aipre_noise_mot_gain = tunning->sw_aiBnrT_noiseAddMot_coeff * (1 << 3);
ai_cfg->aipre_noise_mot_gain = CLIP(ai_cfg->aipre_noise_mot_gain, -64, 63);
ai_cfg->aipre_noise_luma_offset = tunning->sw_aiBnrT_noiseAddLuma_offset;
ai_cfg->aipre_noise_luma_gain = tunning->sw_aiBnrT_noiseAddLuma_coeff;
ai_cfg->aipre_noise_luma_clip = tunning->sw_aiBnrT_noiseAddLumaClip_th* (1 << 10);
ai_cfg->aipre_noise_luma_clip = MIN(ai_cfg->aipre_noise_luma_clip, 0x3FF);
uint16_t gain_tmp = sqrt(1.0 / tunning->sw_aiBnrT_noiseAddLumaStatic_th) * 255.0;
uint16_t ext_tmp = (MAX((int)gain_tmp - ai_cfg->aipre_noise_mot_offset, 0) * ai_cfg->aipre_noise_mot_gain) >> 3;
gain_tmp = MIN(gain_tmp + ext_tmp, 2047);
ai_cfg->aipre_noise_luma_static = MIN(255 * ai_cfg->aipre_gain_ratio / gain_tmp, 128);
ai_cfg->aipre_gain_alpha = 8;
ai_cfg->aipre_global_gain = 128;
ai_cfg->aipre_nar_manual = 0;
ai_cfg->aipre_nar_manual_alpha = 0;
ai_cfg->aipre_narmap_inv = 0;
ai_cfg->pyr_gain_leftshift = 0;
for (int i = 0; i < AIBNR_PREV_LUT_LEN_33; i++) {
float x = (float)i / (AIBNR_PREV_LUT_LEN_33 - 1);
if (btnrCfg_pixDomain_mode == btnr_pixLinearDomain_mode)
{
x = nonLinear(x, 0, nonlinear_ratio, nonlinear_scale);
float a = 1.604;
float b = -0.7553;
float dx = a * pow(MAX(i, 1), b);
x = x + dx / AIBNR_NPU_FEATURE_MAX_1023 * nonlinear_adjust;
}
else
{
x = Linear(x, logScale, 0);
}
ai_cfg->aipre_sigma_y[i] = round(x * AIBNR_NPU_FEATURE_MAX_1023);
isp_aibnr_param->sw_in_comp_y[i] = ai_cfg->aipre_sigma_y[i];
}
for (int i = 0; i < AIBNR_POST_LUT_LEN_33; i++)
{
float x = (float)i / (AIBNR_POST_LUT_LEN_33 - 1);
if (btnrCfg_pixDomain_mode == btnr_pixLinearDomain_mode)
{
x = nonLinear(x, 1, nonlinear_ratio, nonlinear_scale);
}
else
{
x = Linear(x, logScale, 1);
}
isp_aibnr_param->sw_out_decomp_y[i] = round(x * AIBNR_RAW_DATA_MAX_65535);
}
float shot_val = calib->sw_aiBnrC_shotNoise_val * tunning->sw_aiBnrT_shotNr_strg * tunning->sw_aiBnrT_totalNr_strg / 1000;
float read_val = calib->sw_aiBnrC_readNoise_val * tunning->sw_aiBnrT_readNr_strg * tunning->sw_aiBnrT_totalNr_strg / 1000;
float fixed_val = calib->sw_aiBnrC_fixedNoise_val * tunning->sw_aiBnrT_fixedNr_strg * tunning->sw_aiBnrT_totalNr_strg / 1000;
float motion_bias_offset = tunning->sw_aiBnrT_motionBias_offset;
float motion_gain_strg = tunning->sw_aiBnrT_motionGain_strg;
float quant_val = 0;
char model_file[256];
sprintf(model_file, "%s/%s", psta->model_dir.sw_aiBnrCfg_model_dir, tunning->sw_aiBnrT_model_file);
for (i = 0; i < AIBNR_ISO_STEP_MAX; i++) {
if (strcmp(pAibnrModelInfo->model_file[i], model_file) == 0) {
quant_val = pAibnrModelInfo->quant_val[i];
break;
}
}
if (i >= AIBNR_ISO_STEP_MAX) {
quant_val = pAibnrModelInfo->quant_val[0];
LOGE_AIBNR("can not find model file %s, quant_val %f", model_file, quant_val);
}
for (int i = 0; i < AIBNR_SIGMA_LUT_ROW_LEN_9; i++) {
for (int j = 0; j < AIBNR_SIGMA_LUT_COL_LEN_9; j++) {
float wgt = (float)i / (AIBNR_SIGMA_LUT_ROW_LEN_9 - 1);
float lum = (float)j / (AIBNR_SIGMA_LUT_COL_LEN_9 - 1);
float dul = 1;
float ratio = 1;
if (btnrCfg_pixDomain_mode == btnr_pixLinearDomain_mode)
{
if ((lum - 0.01) > 0) {
dul = (nonLinear(lum, 0, nonlinear_ratio, nonlinear_scale) - nonLinear(lum - 0.01, 0, nonlinear_ratio, nonlinear_scale)) * 100;
} else {
dul = (nonLinear(lum + 0.01, 0, nonlinear_ratio, nonlinear_scale) - nonLinear(lum, 0, nonlinear_ratio, nonlinear_scale)) * 100;
}
}
else
{
lum = logTransf(lum, 1, log_offset);
if ((lum - 0.01) > 0)
{
dul = (logTransf(lum, 0, log_offset) - logTransf(lum - 0.01, 0, log_offset)) * 100;
}
else
{
dul = (logTransf(lum + 0.01, 0, log_offset) - logTransf(lum, 0, log_offset)) * 100;
}
ratio = 1 << 4; //12bit -> 16bit
}
float motion_strg = pow(motion_bias_offset / MIN(motion_bias_offset, 1 / (wgt * wgt)), motion_gain_strg);
float sig = MAX(shot_val * lum / preDgain * ratio + read_val, 0) * wgt * wgt * motion_strg + fixed_val;
sig = sqrt(sig) * quant_val * dul * preDgain / ratio * logScale;
sig = MIN(sig, 1);
ai_cfg->pyr_sigma_y[i * AIBNR_SIGMA_LUT_COL_LEN_9 + j] = sig * 255;
}
}
ai_cfg->aipre_scale = 0; // 8 bits, [0, 255]
ai_cfg->aipre_zp = 0; // 8 bits, [-128, 127]
rk_aiq_aibnr_params_print(ai_cfg);
return;
}