xref: /OK3568_Linux_fs/external/camera_engine_rkaiq/rkaiq/algos/aldch/rk_aiq_algo_aldch_itf.cpp (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * rk_aiq_algo_aldch_itf.c
3  *
4  *  Copyright (c) 2019 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 "aldch/rk_aiq_algo_aldch_itf.h"
21 #include "aldch/rk_aiq_types_aldch_algo_prvt.h"
22 #include "rk_aiq_algo_types.h"
23 #include "RkAiqCalibDbV2Helper.h"
24 #include "xcam_log.h"
25 #include "rk_aiq_ldch_generate_mesh.h"
26 
27 RKAIQ_BEGIN_DECLARE
28 
29 
30 static XCamReturn
updateCalibConfig(RkAiqAlgoCom * params)31 updateCalibConfig(RkAiqAlgoCom* params)
32 {
33     LDCHHandle_t hLDCH = (LDCHHandle_t)params->ctx->hLDCH;
34     LDCHContext_t* ldchCtx = (LDCHContext_t*)hLDCH;
35     RkAiqAlgoConfigAldch* rkaiqAldchConfig = (RkAiqAlgoConfigAldch*)params;
36 
37     CalibDbV2_LDCH_t* calib_ldch_db =
38         (CalibDbV2_LDCH_t*)(CALIBDBV2_GET_MODULE_PTR(rkaiqAldchConfig->com.u.prepare.calibv2, aldch));
39     CalibDbV2_Ldch_Param_t* calib_ldch = &calib_ldch_db->param;
40 
41     ldchCtx->camCoeff.cx = calib_ldch->light_center[0];
42     ldchCtx->camCoeff.cy = calib_ldch->light_center[1];
43     ldchCtx->camCoeff.a0 = calib_ldch->coefficient[0];
44     ldchCtx->camCoeff.a2 = calib_ldch->coefficient[1];
45     ldchCtx->camCoeff.a3 = calib_ldch->coefficient[2];
46     ldchCtx->camCoeff.a4 = calib_ldch->coefficient[3];
47 
48     if (calib_ldch->ldch_en) {
49         if (!ldchCtx->ldch_en || calib_ldch->correct_level != hLDCH->correct_level) {
50             aiqGenLdchMeshInit(hLDCH);
51             bool success = aiqGenMesh(hLDCH, calib_ldch->correct_level);
52             if (!success) {
53                 LOGE_ALDCH("lut is not exist");
54                 put_ldch_buf(hLDCH);
55                 return XCAM_RETURN_ERROR_PARAM;
56             }
57         }
58     }
59 
60     ldchCtx->ldch_en = calib_ldch->ldch_en;
61     memcpy(ldchCtx->meshfile, calib_ldch->meshfile, sizeof(ldchCtx->meshfile));
62     ldchCtx->correct_level = calib_ldch->correct_level;
63     ldchCtx->correct_level_max = calib_ldch->correct_level_max;
64 
65     ldchCtx->isAttribUpdated = true;
66 
67     LOGI_ALDCH("en(%d), level(%d-%d), coeff(%f, %f, %f, %f, %f, %f)",
68             calib_ldch->ldch_en,
69             calib_ldch->correct_level,
70             calib_ldch->correct_level_max,
71             calib_ldch->light_center[0],
72             calib_ldch->light_center[1],
73             calib_ldch->coefficient[0],
74             calib_ldch->coefficient[1],
75             calib_ldch->coefficient[2],
76             calib_ldch->coefficient[3]);
77 
78     return XCAM_RETURN_NO_ERROR;
79 }
80 
81 static XCamReturn
create_context(RkAiqAlgoContext ** context,const AlgoCtxInstanceCfg * cfg)82 create_context(RkAiqAlgoContext **context, const AlgoCtxInstanceCfg* cfg)
83 {
84     XCamReturn result = XCAM_RETURN_NO_ERROR;
85 
86     LOG1_ALDCH("%s: (enter)\n", __FUNCTION__ );
87     RkAiqAlgoContext *ctx = new RkAiqAlgoContext();
88     if (ctx == NULL) {
89         LOGE_ALDCH( "%s: create aldch context fail!\n", __FUNCTION__);
90         return XCAM_RETURN_ERROR_MEM;
91     }
92     ctx->hLDCH = new LDCHContext_t;
93     if (ctx->hLDCH == NULL) {
94         LOGE_ALDCH( "%s: create aldch handle fail!\n", __FUNCTION__);
95         return XCAM_RETURN_ERROR_MEM;
96     }
97     /* setup config */
98     memset((void *)(ctx->hLDCH), 0, sizeof(LDCHContext_t) );
99 
100     /* return handle */
101     *context = ctx;
102 
103 #if GENMESH_ONLINE
104     ctx->hLDCH->isAttribUpdated = false;
105     ctx->hLDCH->aldchReadMeshThread = new RKAiqAldchThread(ctx->hLDCH);
106     /* ctx->hLDCH->aldchReadMeshThread->triger_start(); */
107     /* ctx->hLDCH->aldchReadMeshThread->start(); */
108 #endif
109 
110     LDCHHandle_t ldchCtx = ctx->hLDCH;
111     CalibDbV2_LDCH_t* calib_ldch_db =
112             (CalibDbV2_LDCH_t*)(CALIBDBV2_GET_MODULE_PTR(cfg->calibv2, aldch));
113     CalibDbV2_Ldch_Param_t* calib_ldch = &calib_ldch_db->param;
114 
115     ldchCtx->ldch_en = calib_ldch->ldch_en;
116     memcpy(ldchCtx->meshfile, calib_ldch->meshfile, sizeof(ldchCtx->meshfile));
117 #if GENMESH_ONLINE
118     ldchCtx->camCoeff.cx = calib_ldch->light_center[0];
119     ldchCtx->camCoeff.cy = calib_ldch->light_center[1];
120     ldchCtx->camCoeff.a0 = calib_ldch->coefficient[0];
121     ldchCtx->camCoeff.a2 = calib_ldch->coefficient[1];
122     ldchCtx->camCoeff.a3 = calib_ldch->coefficient[2];
123     ldchCtx->camCoeff.a4 = calib_ldch->coefficient[3];
124     LOGI_ALDCH("(%s) len light center(%.16f, %.16f)\n",
125             __FUNCTION__,
126             ldchCtx->camCoeff.cx, ldchCtx->camCoeff.cy);
127     LOGI_ALDCH("(%s) len coefficient(%.16f, %.16f, %.16f, %.16f)\n",
128             __FUNCTION__,
129             ldchCtx->camCoeff.a0, ldchCtx->camCoeff.a2,
130             ldchCtx->camCoeff.a3, ldchCtx->camCoeff.a4);
131 #endif
132     ldchCtx->correct_level = calib_ldch->correct_level;
133     ldchCtx->correct_level_max = calib_ldch->correct_level_max;
134 
135     LOGI_ALDCH("ldch en %d, meshfile: %s, correct_level-max: %d-%d from xml file",
136                calib_ldch->ldch_en,
137                ldchCtx->meshfile,
138                ldchCtx->correct_level,
139                ldchCtx->correct_level_max);
140 
141     return XCAM_RETURN_NO_ERROR;
142 }
143 
144 static XCamReturn
destroy_context(RkAiqAlgoContext * context)145 destroy_context(RkAiqAlgoContext *context)
146 {
147     LDCHHandle_t hLDCH = (LDCHHandle_t)context->hLDCH;
148     LDCHContext_t* ldchCtx = (LDCHContext_t*)hLDCH;
149 
150 #if GENMESH_ONLINE
151     if (!hLDCH->aldchReadMeshThread->is_empty())
152         hLDCH->aldchReadMeshThread->clear_attr();
153     ldchCtx->aldchReadMeshThread->triger_stop();
154     ldchCtx->aldchReadMeshThread->stop();
155 #endif
156 
157 #if GENMESH_ONLINE
158 	genLdchMeshDeInit(ldchCtx->ldchParams);
159 #endif
160     release_ldch_buf(ldchCtx);
161     delete context->hLDCH;
162     context->hLDCH = NULL;
163     delete context;
164     context = NULL;
165     return XCAM_RETURN_NO_ERROR;
166 }
167 
168 static XCamReturn
prepare(RkAiqAlgoCom * params)169 prepare(RkAiqAlgoCom* params)
170 {
171     LDCHHandle_t hLDCH = (LDCHHandle_t)params->ctx->hLDCH;
172     LDCHContext_t* ldchCtx = (LDCHContext_t*)hLDCH;
173     RkAiqAlgoConfigAldch* rkaiqAldchConfig = (RkAiqAlgoConfigAldch*)params;
174 
175     ldchCtx->src_width = params->u.prepare.sns_op_width;
176     ldchCtx->src_height = params->u.prepare.sns_op_height;
177     ldchCtx->dst_width = params->u.prepare.sns_op_width;
178     ldchCtx->dst_height = params->u.prepare.sns_op_height;
179     ldchCtx->resource_path = rkaiqAldchConfig->resource_path;
180     ldchCtx->share_mem_ops = rkaiqAldchConfig->mem_ops_ptr;
181 
182     bool config_calib = !!(params->u.prepare.conf_type & RK_AIQ_ALGO_CONFTYPE_UPDATECALIB);
183     if (config_calib) {
184         updateCalibConfig(params);
185         return XCAM_RETURN_NO_ERROR;
186     }
187 
188 #if GENMESH_ONLINE
189     // process the new attrib set before prepare
190     hLDCH->aldchReadMeshThread->triger_stop();
191     hLDCH->aldchReadMeshThread->stop();
192     if (!hLDCH->aldchReadMeshThread->is_empty()) {
193         hLDCH->aldchReadMeshThread->clear_attr();
194         ldchCtx->isAttribUpdated = true;
195     }
196 
197     if (ldchCtx->isAttribUpdated) {
198         ldchCtx->ldch_en = ldchCtx->user_config.en;
199         ldchCtx->correct_level = ldchCtx->user_config.correct_level;
200         ldchCtx->isAttribUpdated = false;
201     } else {
202         ldchCtx->user_config.en = ldchCtx->ldch_en;
203         ldchCtx->user_config.correct_level = ldchCtx->correct_level;
204     }
205 
206     hLDCH->aldchReadMeshThread->triger_start();
207     hLDCH->aldchReadMeshThread->start();
208     if (!ldchCtx->ldch_en)
209         return XCAM_RETURN_NO_ERROR;
210 
211     if (aiqGenLdchMeshInit(ldchCtx) == XCAM_RETURN_NO_ERROR) {
212         bool success = aiqGenMesh(hLDCH, ldchCtx->correct_level);
213         if (!success) {
214             LOGW_ALDCH("lut is not exist");
215             put_ldch_buf(hLDCH);
216             ldchCtx->ldch_en = 0;
217         }
218     }
219 #else
220     if (!ldchCtx->ldch_en)
221         return XCAM_RETURN_NO_ERROR;
222 
223     char filename[512];
224     sprintf(filename, "%s/%s/mesh_level%d.bin",
225             ldchCtx->resource_path,
226             ldchCtx->meshfile,
227             ldchCtx->correct_level);
228     bool ret = read_mesh_from_file(ldchCtx, filename);
229     if (!ret)
230         ldchCtx->ldch_en = 0;
231 #endif
232 
233     return XCAM_RETURN_NO_ERROR;
234 }
235 
236 static XCamReturn
pre_process(const RkAiqAlgoCom * inparams,RkAiqAlgoResCom * outparams)237 pre_process(const RkAiqAlgoCom* inparams, RkAiqAlgoResCom* outparams)
238 {
239     return XCAM_RETURN_NO_ERROR;
240 }
241 
242 static XCamReturn
processing(const RkAiqAlgoCom * inparams,RkAiqAlgoResCom * outparams)243 processing(const RkAiqAlgoCom* inparams, RkAiqAlgoResCom* outparams)
244 {
245     LDCHHandle_t hLDCH = (LDCHHandle_t)inparams->ctx->hLDCH;
246     LDCHContext_t* ldchCtx = (LDCHContext_t*)hLDCH;
247     RkAiqAlgoProcResAldch* ldchPreOut = (RkAiqAlgoProcResAldch*)outparams;
248 
249     bool update_params = false;
250     if (inparams->u.proc.init) {
251         update_params = true;
252     } else {
253         if (ldchCtx->isAttribUpdated) {
254             ldchCtx->isAttribUpdated = false;
255             update_params = true;
256         } else {
257             update_params = false;
258         }
259 
260         LOGV_ALDCH("(%s) en(%d), level(%d), user en(%d), level(%d), result update(%d)\n",
261                 __FUNCTION__,
262                 ldchCtx->ldch_en,
263                 ldchCtx->correct_level,
264                 ldchCtx->user_config.en,
265                 ldchCtx->user_config.correct_level,
266                 update_params);
267     }
268 
269     if (update_params) {
270         ldchPreOut->ldch_result->sw_ldch_en = ldchCtx->ldch_en;
271         ldchPreOut->ldch_result->lut_h_size = ldchCtx->lut_h_size;
272         ldchPreOut->ldch_result->lut_v_size = ldchCtx->lut_v_size;
273         ldchPreOut->ldch_result->lut_map_size = ldchCtx->lut_mapxy_size;
274         if (ldchCtx->ldch_en) {
275             if (!ldchCtx->ldch_mem_info) {
276                 LOGE_ALDCH("no available ldch buf, ldch_mem_info: %p", ldchCtx->ldch_mem_info);
277                 outparams->cfg_update = false;
278                 return XCAM_RETURN_NO_ERROR;
279             }
280 
281             ldchPreOut->ldch_result->lut_mapxy_buf_fd = ldchCtx->ldch_mem_info->fd;
282         }
283     }
284     outparams->cfg_update = update_params;
285 
286     return XCAM_RETURN_NO_ERROR;
287 }
288 
289 static XCamReturn
post_process(const RkAiqAlgoCom * inparams,RkAiqAlgoResCom * outparams)290 post_process(const RkAiqAlgoCom* inparams, RkAiqAlgoResCom* outparams)
291 {
292     return XCAM_RETURN_NO_ERROR;
293 }
294 
295 RkAiqAlgoDescription g_RkIspAlgoDescAldch = {
296     .common = {
297         .version = RKISP_ALGO_ALDCH_VERSION,
298         .vendor  = RKISP_ALGO_ALDCH_VENDOR,
299         .description = RKISP_ALGO_ALDCH_DESCRIPTION,
300         .type    = RK_AIQ_ALGO_TYPE_ALDCH,
301         .id      = 0,
302         .create_context  = create_context,
303         .destroy_context = destroy_context,
304     },
305     .prepare = prepare,
306     .pre_process = NULL,
307     .processing = processing,
308     .post_process = NULL,
309 };
310 
311 RKAIQ_END_DECLARE
312 
313 
loop()314 bool RKAiqAldchThread::loop()
315 {
316     XCamReturn ret = XCAM_RETURN_NO_ERROR;
317     ENTER_ANALYZER_FUNCTION();
318 
319     const static int32_t timeout = -1;
320     SmartPtr<rk_aiq_ldch_cfg_t> attrib = mAttrQueue.pop (timeout);
321 
322     if (!attrib.ptr()) {
323         LOGW_ALDCH("RKAiqAldchThread got empty attrib, stop thread");
324         return false;
325     }
326 #if GENMESH_ONLINE
327     if (attrib->en) {
328         if (!hLDCH->ldch_en || attrib->correct_level != hLDCH->correct_level) {
329             aiqGenLdchMeshInit(hLDCH);
330             bool success = aiqGenMesh(hLDCH, attrib->correct_level);
331             if (!success) {
332                 LOGW_ALDCH("lut is not exist");
333                 put_ldch_buf(hLDCH);
334             }
335         }
336     }
337 
338     hLDCH->ldch_en = hLDCH->user_config.en;
339     hLDCH->correct_level = hLDCH->user_config.correct_level;
340 #endif
341     if (ret == XCAM_RETURN_NO_ERROR) {
342         hLDCH->isAttribUpdated = true;
343         LOGV_ALDCH("ldch en(%d), level(%d)\n", hLDCH->ldch_en, hLDCH->correct_level);
344         return true;
345     }
346 
347     LOGE_ALDCH("RKAiqAldchThread failed to read mesh table!");
348 
349     EXIT_ANALYZER_FUNCTION();
350 
351     return false;
352 }
353