xref: /OK3568_Linux_fs/external/camera_engine_rkaiq/rkaiq/algos/amd/rk_aiq_algo_amd_itf.cpp (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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