1 /*
2 * rk_aiq_algo_amd_itf.c
3 *
4 * Copyright (c) 2021 Rockchip Corporation
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 */
19
20 #include "amd/rk_aiq_algo_amd_itf.h"
21 #include "xcam_log.h"
22 #include "amd/rk_aiq_types_algo_amd_prvt.h"
23 #include "md_lib/motion_detect.h"
24 #include "media_buffer/media_buffer_pool.h"
25 #include "rk_aiq_algo_types.h"
26 #include "RkAiqCalibDbV2Helper.h"
27
28 RKAIQ_BEGIN_DECLARE
29
30 static uint8_t static_ratio_l;
31 static uint8_t static_ratio_l_bit;
32 static uint8_t static_ratio_r_bit;
33 static int gain_blk_isp_stride;
34
35 static XCamReturn
create_context(RkAiqAlgoContext ** context,const AlgoCtxInstanceCfg * cfg)36 create_context(RkAiqAlgoContext **context, const AlgoCtxInstanceCfg* cfg)
37 {
38 RkAiqAlgoContext *ctx = new RkAiqAlgoContext();
39 if (ctx == NULL) {
40 LOGE_AMD( "%s: create amd context fail!\n", __FUNCTION__);
41 return XCAM_RETURN_ERROR_MEM;
42 }
43 memset(ctx, 0, sizeof(RkAiqAlgoContext));
44 ctx->amdCtx.calib = cfg->calib;
45 ctx->amdCtx.calibv2 = cfg->calibv2;
46
47 if (ctx->amdCtx.calib) {
48 CalibDb_MFNR_t *calib_mfnr =
49 (CalibDb_MFNR_t*)(CALIBDB_GET_MODULE_PTR(ctx->amdCtx.calib, mfnr));
50 if (!calib_mfnr)
51 LOGE_AMD( "%s: get calib_mfnr fail!\n", __FUNCTION__);
52 } else if (ctx->amdCtx.calibv2) {
53 CalibDbV2_MFNR_t* calibv2_mfnr =
54 (CalibDbV2_MFNR_t*)(CALIBDBV2_GET_MODULE_PTR(ctx->amdCtx.calibv2, mfnr_v1));
55 if (calibv2_mfnr) {
56 ctx->amdCtx.enable = calibv2_mfnr->TuningPara.motion_detect_en;
57 ctx->amdCtx.motion = (CalibDbV2_MFNR_TuningPara_Motion_t)calibv2_mfnr->TuningPara.Motion;
58 }else {
59 LOGE_AMD( "%s: get calibv2_mfnr fail!\n", __FUNCTION__);
60 }
61 }
62
63 *context = ctx;
64
65 return XCAM_RETURN_NO_ERROR;
66 }
67
68 static XCamReturn
destroy_context(RkAiqAlgoContext * context)69 destroy_context(RkAiqAlgoContext *context)
70 {
71 if (context->amdCtx.pPreAlpha)
72 free(context->amdCtx.pPreAlpha);
73 if (context->amdCtx.pTmpBuf)
74 free(context->amdCtx.pTmpBuf);
75
76 for (int i=0; i<AMD_RATIO_BUF_NUM; i++) {
77 if (context->amdCtx.ratio_out[i])
78 free(context->amdCtx.ratio_out[i]);
79 }
80 if (context->amdCtx.spImage_prev)
81 context->amdCtx.spImage_prev->unref(context->amdCtx.spImage_prev);//release prev image
82 if (context->amdCtx.ispGain_prev)
83 context->amdCtx.ispGain_prev->unref(context->amdCtx.ispGain_prev);//release prev gain
84
85 MediaBufPoolDestroy(&context->amdCtx.BufPool);
86 if (context->amdCtx.BufPoolMem.pMetaDataMemory)
87 free(context->amdCtx.BufPoolMem.pMetaDataMemory);
88
89 delete context;
90 return XCAM_RETURN_NO_ERROR;
91 }
92
93 static XCamReturn
prepare(RkAiqAlgoCom * params)94 prepare(RkAiqAlgoCom* params)
95 {
96 RkAiqAlgoConfigAmd* pCfgParam = (RkAiqAlgoConfigAmd*)params;
97 RkAiqAlgoContext* ctx = params->ctx;
98
99 if(!!(params->u.prepare.conf_type & RK_AIQ_ALGO_CONFTYPE_UPDATECALIB )){
100 if (pCfgParam->com.u.prepare.calib) {
101 CalibDb_MFNR_t *calib_mfnr =
102 (CalibDb_MFNR_t*)(CALIBDB_GET_MODULE_PTR(pCfgParam->com.u.prepare.calib, mfnr));
103 if (!calib_mfnr)
104 LOGE_AMD( "%s: get calib_mfnr fail!\n", __FUNCTION__);
105 } else if (pCfgParam->com.u.prepare.calibv2) {
106 CalibDbV2_MFNR_t* calibv2_mfnr =
107 (CalibDbV2_MFNR_t*)(CALIBDBV2_GET_MODULE_PTR(pCfgParam->com.u.prepare.calibv2, mfnr_v1));
108 if (calibv2_mfnr) {
109 ctx->amdCtx.enable = calibv2_mfnr->TuningPara.motion_detect_en;
110 ctx->amdCtx.motion = (CalibDbV2_MFNR_TuningPara_Motion_t)calibv2_mfnr->TuningPara.Motion;
111 }else {
112 LOGE_AMD( "%s: get calibv2_mfnr fail!\n", __FUNCTION__);
113 }
114 }
115 }
116
117 if (!ctx->amdCtx.enable)
118 return XCAM_RETURN_NO_ERROR;
119
120 ctx->amdCtx.imgAlignedW = pCfgParam->spAlignedW;
121 ctx->amdCtx.imgAlignedH = pCfgParam->spAlignedH;
122 ctx->amdCtx.imgWidth = pCfgParam->spWidth;
123 ctx->amdCtx.imgHeight = pCfgParam->spHeight;
124
125 int gain_blk_isp_w = ctx->amdCtx.imgWidth;
126 gain_blk_isp_stride = ((gain_blk_isp_w + 15) / 16) * 16;
127 int gain_blk_isp_h = ctx->amdCtx.imgHeight;
128 int ratio_stride = ((gain_blk_isp_w + 7) / 8) * 8;
129 int gain_kg_tile_h_align = (gain_blk_isp_h + 15) & 0xfff0;
130
131 static_ratio_l_bit = RATIO_BITS_NUM;
132 static_ratio_r_bit = RATIO_BITS_R_NUM;
133 static_ratio_l = 1 << static_ratio_l_bit;
134
135
136 ctx->amdCtx.ratio_size = ratio_stride * gain_kg_tile_h_align;
137 ctx->amdCtx.pPreAlpha = (uint8_t*)malloc(ctx->amdCtx.ratio_size);
138 memset(ctx->amdCtx.pPreAlpha, 0, ctx->amdCtx.ratio_size);
139
140 ctx->amdCtx.pTmpBuf = (short*)malloc(gain_blk_isp_w * gain_blk_isp_h * 6 * sizeof(ctx->amdCtx.pTmpBuf[0]));
141
142 for (int i=0; i<AMD_RATIO_BUF_NUM; i++) {
143 ctx->amdCtx.ratio_out[i] = (uint8_t*)malloc(ctx->amdCtx.ratio_size);
144 memset(ctx->amdCtx.ratio_out[i], static_ratio_l, ctx->amdCtx.ratio_size);
145 }
146 //create buffer pool
147 ctx->amdCtx.BufPoolConfig.bufNum = AMD_RATIO_BUF_NUM;
148 ctx->amdCtx.BufPoolConfig.maxBufNum = AMD_RATIO_BUF_NUM;
149 ctx->amdCtx.BufPoolConfig.bufSize = ctx->amdCtx.ratio_size;
150 ctx->amdCtx.BufPoolConfig.bufAlign = 1;
151 ctx->amdCtx.BufPoolConfig.metaDataSizeMediaBuf = sizeof(MotionBufMetaData_t);
152 ctx->amdCtx.BufPoolConfig.flags = 0;
153
154 MediaBufPoolGetSize(&ctx->amdCtx.BufPoolConfig);
155
156 ctx->amdCtx.BufPoolMem.pMetaDataMemory = malloc(ctx->amdCtx.BufPoolConfig.metaDataMemSize);
157 ctx->amdCtx.BufPoolMem.pBufferMemory = (void *)ctx->amdCtx.ratio_out;
158 MediaBufPoolCreate(&ctx->amdCtx.BufPool, &ctx->amdCtx.BufPoolConfig, ctx->amdCtx.BufPoolMem);
159
160 return XCAM_RETURN_NO_ERROR;
161 }
162
163 static XCamReturn
pre_process(const RkAiqAlgoCom * inparams,RkAiqAlgoResCom * outparams)164 pre_process(const RkAiqAlgoCom* inparams, RkAiqAlgoResCom* outparams)
165 {
166 return XCAM_RETURN_NO_ERROR;
167 }
168
select_motion_params_by_iso(Mt_Params_Select_t * motion_params_selected,uint32_t iso,CalibDbV2_MFNR_TuningPara_Motion_t & motion_full_params)169 XCamReturn select_motion_params_by_iso(Mt_Params_Select_t *motion_params_selected, uint32_t iso, CalibDbV2_MFNR_TuningPara_Motion_t &motion_full_params)
170 {
171 float gain = iso / 50;
172 float gain_f = log2(gain);
173 uint8_t gain_l = ceil(gain_f);
174 uint8_t gain_r = floor(gain_f);
175 float ratio = (float)(gain_f - gain_r);
176
177 motion_params_selected->enable = true;//motion_full_params.enable;
178 motion_params_selected->sigmaHScale = (motion_full_params.Motion_ISO[gain_l].sigmaHScale * ratio + motion_full_params.Motion_ISO[gain_r].sigmaHScale * (1 - ratio));
179 motion_params_selected->sigmaLScale = (motion_full_params.Motion_ISO[gain_l].sigmaLScale * ratio + motion_full_params.Motion_ISO[gain_r].sigmaLScale * (1 - ratio));
180 motion_params_selected->light_clp = (motion_full_params.Motion_ISO[gain_l].lightClp * ratio + motion_full_params.Motion_ISO[gain_r].lightClp * (1 - ratio));
181 motion_params_selected->uv_weight = (motion_full_params.Motion_ISO[gain_l].uvWeight * ratio + motion_full_params.Motion_ISO[gain_r].uvWeight * (1 - ratio));
182 motion_params_selected->yuvnr_gain_scale[0] = (motion_full_params.Motion_ISO[gain_l].yuvnrGainScale0 * ratio + motion_full_params.Motion_ISO[gain_r].yuvnrGainScale0 * (1 - ratio));
183 motion_params_selected->yuvnr_gain_scale[1] = (motion_full_params.Motion_ISO[gain_l].yuvnrGainScale1 * ratio + motion_full_params.Motion_ISO[gain_r].yuvnrGainScale1 * (1 - ratio));
184 motion_params_selected->yuvnr_gain_scale[2] = (motion_full_params.Motion_ISO[gain_l].yuvnrGainScale2 * ratio + motion_full_params.Motion_ISO[gain_r].yuvnrGainScale2 * (1 - ratio));
185 motion_params_selected->frame_limit_y = (motion_full_params.Motion_ISO[gain_l].frame_limit_y * ratio + motion_full_params.Motion_ISO[gain_r].frame_limit_y * (1 - ratio));
186 motion_params_selected->frame_limit_uv = (motion_full_params.Motion_ISO[gain_l].frame_limit_uv * ratio + motion_full_params.Motion_ISO[gain_r].frame_limit_uv * (1 - ratio));
187 motion_params_selected->mfnr_sigma_scale = (motion_full_params.Motion_ISO[gain_l].mfnrSigmaScale * ratio + motion_full_params.Motion_ISO[gain_r].mfnrSigmaScale * (1 - ratio));
188 if(motion_params_selected->mfnr_sigma_scale > 0)
189 static_ratio_r_bit = static_ratio_l_bit - ceil(log2(motion_params_selected->mfnr_sigma_scale));
190 //static_ratio_r_bit = static_ratio_l_bit - ceil(log2(motion_params_selected->mfnr_sigma_scale)) - ceil(log2(motion_params_selected->motion_dn_str));
191 else
192 LOGE_AMD("motion_params_selected->mfnr_sigma_scale %d is out of range\n", motion_params_selected->mfnr_sigma_scale);
193
194 // motion_params_selected->gain_scale_l_y = (motion_full_params.Motion_ISO[gain_l].reserved7 * ratio + motion_full_params.Motion_ISO[gain_r].reserved7 * (1 - ratio));
195 // motion_params_selected->gain_scale_l_uv = (motion_full_params.Motion_ISO[gain_l].reserved6 * ratio + motion_full_params.Motion_ISO[gain_r].reserved6 * (1 - ratio));
196 // motion_params_selected->gain_scale_h_y = (motion_full_params.Motion_ISO[gain_l].reserved5 * ratio + motion_full_params.Motion_ISO[gain_r].reserved5 * (1 - ratio));
197 // motion_params_selected->gain_scale_h_uv = (motion_full_params.Motion_ISO[gain_l].reserved4 * ratio + motion_full_params.Motion_ISO[gain_r].reserved4 * (1 - ratio));
198 LOGD_AMD("selected:gain_r %d gain_l:%d iso %d ratio %f, %f,%f,%f,%f,%f,%f,%f %f %6f %2f %2f %2f %2f %d\n",gain_r,gain_l,iso, ratio,
199 motion_params_selected->sigmaHScale,motion_params_selected->sigmaLScale ,motion_params_selected->light_clp,motion_params_selected->uv_weight,
200 motion_params_selected->yuvnr_gain_scale[0],motion_params_selected->yuvnr_gain_scale[1],motion_params_selected->yuvnr_gain_scale[2],
201 motion_params_selected->frame_limit_y,motion_params_selected->frame_limit_uv, motion_params_selected->gain_scale_l_y, motion_params_selected->gain_scale_l_uv,
202 motion_params_selected->gain_scale_h_y, motion_params_selected->gain_scale_h_uv, 0);
203 return XCAM_RETURN_NO_ERROR;
204 }
205
206
207
208 static XCamReturn
processing(const RkAiqAlgoCom * inparams,RkAiqAlgoResCom * outparams)209 processing(const RkAiqAlgoCom* inparams, RkAiqAlgoResCom* outparams)
210 {
211 RkAiqAlgoProcResAmd* res = (RkAiqAlgoProcResAmd*)outparams;
212 RkAiqAlgoContext* ctx = inparams->ctx;
213 RkAiqAlgoProcAmd *pAmdProcParams = (RkAiqAlgoProcAmd*)inparams;
214 rk_aiq_amd_algo_stat_t *stats = &pAmdProcParams->stats;
215 int ISO = 50;
216
217 if (!ctx->amdCtx.enable)
218 return XCAM_RETURN_NO_ERROR;
219
220
221 return XCAM_RETURN_NO_ERROR;//test
222
223
224 if (!stats->ispGain && !stats->spImage) //first time coming without value, filter it.
225 return XCAM_RETURN_NO_ERROR;
226
227 if (ctx->amdCtx.ispGain_prev == NULL) {
228 ctx->amdCtx.ispGain_prev = stats->ispGain;
229 ctx->amdCtx.ispGain_prev->ref(ctx->amdCtx.ispGain_prev);
230 LOGD_AMD("ispGain>>>frame_id=%d,fd=%d\n",ctx->amdCtx.ispGain_prev->frame_id, ctx->amdCtx.ispGain_prev->get_fd(ctx->amdCtx.ispGain_prev));
231 ctx->amdCtx.spImage_prev = stats->spImage;
232 ctx->amdCtx.spImage_prev->ref(ctx->amdCtx.spImage_prev);
233 LOGD_AMD("spImage>>>frame_id=%d,fd=%d\n",ctx->amdCtx.spImage_prev->frame_id, ctx->amdCtx.spImage_prev->get_fd(ctx->amdCtx.spImage_prev));
234 return XCAM_RETURN_NO_ERROR;
235 }
236 if (ctx->amdCtx.ispGain == NULL) {
237 ctx->amdCtx.ispGain = stats->ispGain;
238 ctx->amdCtx.ispGain->ref(ctx->amdCtx.ispGain);
239 LOGD_AMD("ispGain>>>frame_id=%d,fd=%d\n",ctx->amdCtx.ispGain->frame_id, ctx->amdCtx.ispGain->get_fd(ctx->amdCtx.ispGain));
240 ctx->amdCtx.spImage = stats->spImage;
241 ctx->amdCtx.spImage->ref(ctx->amdCtx.spImage);
242 LOGD_AMD("spImage>>>frame_id=%d,fd=%d\n",ctx->amdCtx.spImage->frame_id, ctx->amdCtx.spImage->get_fd(ctx->amdCtx.spImage));
243 }
244
245 Mt_Params_Select_t mparams_selected;
246 select_motion_params_by_iso(&mparams_selected, ISO, ctx->amdCtx.motion);
247
248 assert ( ctx->amdCtx.ispGain && ctx->amdCtx.ispGain_prev && ctx->amdCtx.spImage && ctx->amdCtx.spImage_prev );
249 uint8_t *pCurGain = ctx->amdCtx.ispGain->map(ctx->amdCtx.ispGain);
250 uint8_t *pPreGain = ctx->amdCtx.ispGain_prev->map(ctx->amdCtx.ispGain_prev);
251 uint8_t *pCurIn = ctx->amdCtx.spImage->map(ctx->amdCtx.spImage);
252 uint8_t *pPreIn = ctx->amdCtx.spImage_prev->map(ctx->amdCtx.spImage_prev);
253 assert ( pCurGain && pPreGain && pCurIn && pPreIn );
254
255 int imgStride = XCAM_ALIGN_UP(ctx->amdCtx.imgAlignedW, 32);
256 LOGD_AMD("motion detect start,%d,%d",ctx->amdCtx.imgAlignedH,ctx->amdCtx.imgAlignedW);
257 MediaBuffer_t* mediabuf = MediaBufPoolGetBuffer(&ctx->amdCtx.BufPool);
258 if (mediabuf) {
259 LOGD_AMD("MediaBufPool get free buffer, baseaddress %p",mediabuf->pBaseAddress);
260 MotionBufMetaData_t *metadata = (MotionBufMetaData_t *)mediabuf->pMetaData;
261 metadata->frame_id = ctx->amdCtx.spImage->frame_id;
262 }
263 motion_detect(pCurIn, pPreIn, ctx->amdCtx.pTmpBuf, mediabuf->pBaseAddress, ctx->amdCtx.pPreAlpha, (uint8_t*)pCurGain,
264 ctx->amdCtx.imgAlignedH, imgStride, ctx->amdCtx.imgHeight, ctx->amdCtx.imgWidth, gain_blk_isp_stride,
265 mparams_selected.sigmaHScale, mparams_selected.sigmaLScale, mparams_selected.uv_weight, mparams_selected.light_clp, static_ratio_r_bit);
266 LOGD_AMD("motion detect end");
267
268 ctx->amdCtx.spImage->unmap(ctx->amdCtx.spImage);
269 ctx->amdCtx.spImage_prev->unmap(ctx->amdCtx.spImage_prev);
270 ctx->amdCtx.ispGain->unmap(ctx->amdCtx.ispGain);
271 ctx->amdCtx.ispGain_prev->unmap(ctx->amdCtx.ispGain_prev);
272 //switch image
273 ctx->amdCtx.spImage_prev->unref(ctx->amdCtx.spImage_prev);//release prev image
274 ctx->amdCtx.ispGain_prev->unref(ctx->amdCtx.ispGain_prev);//release prev gain
275 ctx->amdCtx.spImage_prev = ctx->amdCtx.spImage;
276 ctx->amdCtx.ispGain_prev = ctx->amdCtx.ispGain;
277 ctx->amdCtx.spImage = NULL;
278 ctx->amdCtx.ispGain = NULL;
279
280 #if 0
281 //output result
282 int prev_index = (ctx->amdCtx.cur_index -1 + AMD_RATIO_BUF_NUM) % AMD_RATIO_BUF_NUM;
283 ctx->amdCtx.params.ratio_prev = ctx->amdCtx.ratio_out[prev_index];//first time it's not correct,but just first frame only, it's okay.
284 ctx->amdCtx.params.ratio_cur = ctx->amdCtx.ratio_out[ctx->amdCtx.cur_index];
285 ctx->amdCtx.params.ratio_size = ctx->amdCtx.ratio_size;
286 res_com->amd_proc_res = ctx->amdCtx.params;
287 ctx->amdCtx.cur_index = (ctx->amdCtx.cur_index + 1) % AMD_RATIO_BUF_NUM;
288 #endif
289 ctx->amdCtx.params.st_ratio = mediabuf;
290 res->amd_proc_res = ctx->amdCtx.params;
291 return XCAM_RETURN_NO_ERROR;
292 }
293
294 static XCamReturn
post_process(const RkAiqAlgoCom * inparams,RkAiqAlgoResCom * outparams)295 post_process(const RkAiqAlgoCom* inparams, RkAiqAlgoResCom* outparams)
296 {
297 return XCAM_RETURN_NO_ERROR;
298 }
299
300 RkAiqAlgoDescription g_RkIspAlgoDescAmd = {
301 .common = {
302 .version = RKISP_ALGO_AMD_VERSION,
303 .vendor = RKISP_ALGO_AMD_VENDOR,
304 .description = RKISP_ALGO_AMD_DESCRIPTION,
305 .type = RK_AIQ_ALGO_TYPE_AMD,
306 .id = 0,
307 .create_context = create_context,
308 .destroy_context = destroy_context,
309 },
310 .prepare = prepare,
311 .pre_process = NULL,
312 .processing = processing,
313 .post_process = NULL,
314 };
315
316 RKAIQ_END_DECLARE
317