1 /*
2 * Copyright (c) 2021 Rockchip Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
17
18 #include "scene_manager.h"
19 #include "RkAiqCalibDbV2.h"
20 #include "j2s.h"
21 #include <fcntl.h>
22 #include <sys/stat.h>
23 #include <sys/types.h>
24 #include <unistd.h>
25
26 namespace RkCam {
27
28 std::map<std::string, AiqScene> RkAiqSceneManager::sceneMap;
29
loadIQFile(const char * name)30 cJSON *RkAiqSceneManager::loadIQFile(const char *name) {
31 char *json_data = NULL;
32 size_t json_data_size = 0;
33 cJSON *out_json = NULL;
34
35 json_data = (char *)j2s_read_file(name, &json_data_size);
36 out_json = cJSON_Parse(json_data);
37 if (json_data) {
38 free(json_data);
39 }
40
41 return out_json;
42 }
43
addScene(const char * name,const char * base,const char * fragment)44 int RkAiqSceneManager::addScene(const char *name, const char *base,
45 const char *fragment) {
46 sceneMap[name] = std::make_pair(std::string(base), std::string(fragment));
47
48 return 0;
49 }
50
addScene(const char * name,AiqScene scene)51 int RkAiqSceneManager::addScene(const char *name, AiqScene scene) {
52 sceneMap[name] = scene;
53 return 0;
54 }
55
matchScene(const char * name)56 AiqScene RkAiqSceneManager::matchScene(const char *name) {
57 auto search = sceneMap.find(std::string(name));
58
59 if (search != sceneMap.end()) {
60 return search->second;
61 } else {
62 std::cout << "Not found\n";
63 }
64
65 return AiqScene();
66 }
67
getSceneIQ(const char * base,const char * fragment)68 const char *RkAiqSceneManager::getSceneIQ(const char *base,
69 const char *fragment) {
70 cJSON *base_json = NULL;
71 cJSON *fragment_json = NULL;
72 cJSON *out_json = NULL;
73
74 base_json = loadIQFile(base);
75 if (!base_json) {
76 printf("Error before: [%s]\n", cJSON_GetErrorPtr());
77 } else {
78 char *out = cJSON_Print(base_json);
79 // printf("%s\n", out);
80 free(out);
81 }
82
83 fragment_json = loadIQFile(fragment);
84 if (!fragment_json) {
85 printf("Error before: [%s]\n", cJSON_GetErrorPtr());
86 } else {
87 char *out = cJSON_Print(fragment_json);
88 // printf("%s\n", out);
89 free(out);
90 }
91
92 // foreach fragment json obj, if fragment first level son obj is not empty
93 // then override base json's same object
94 if (cJSON_Compare(base_json, fragment_json, 1)) {
95 printf("same iq files, do nothing!\n");
96 char *out = cJSON_Print(base_json);
97 return out;
98 }
99
100 for (int i = 0; i < cJSON_GetArraySize(base_json); i++) {
101 printf("[%d]:", i);
102 cJSON *item = cJSON_GetArrayItem(base_json, i);
103 if (cJSON_Invalid != item->type) {
104 printf("[%s]\n", item->string);
105 // printJson(item);
106 }
107 }
108
109 out_json = cJSON_Duplicate(base_json, 1);
110
111 // FIXME: memery leack issue
112 for (int i = 0; i < cJSON_GetArraySize(fragment_json); i++) {
113 printf("[%d]:", i);
114 cJSON *item = cJSON_GetArrayItem(fragment_json, i);
115 if (cJSON_Invalid != item->type) {
116 printf("[%s]\n", item->string);
117 // printJson(item);
118 cJSON_ReplaceItemInObjectCaseSensitive(out_json, item->string,
119 cJSON_Duplicate(item, 1));
120 }
121 }
122
123 printf("new json:>\n%s\n", cJSON_Print(out_json));
124
125 cJSON_Delete(base_json);
126 cJSON_Delete(fragment_json);
127
128 return cJSON_Print(out_json);
129 }
130
getSceneIQ(AiqScene scene)131 const char *RkAiqSceneManager::getSceneIQ(AiqScene scene) {
132 if (access(scene.first.c_str(), F_OK)) {
133 printf("[RkAiqSceneManager]: access %s failed\n", scene.first.c_str());
134 return NULL;
135 }
136
137 if (access(scene.second.c_str(), F_OK)) {
138 printf("[RkAiqSceneManager]: access %s failed\n", scene.first.c_str());
139 return NULL;
140 }
141
142 return getSceneIQ(scene.first.c_str(), scene.second.c_str());
143 }
144
getSceneIQ(const char * scene)145 const char *RkAiqSceneManager::getSceneIQ(const char *scene) {
146 return getSceneIQ(matchScene(scene));
147 }
148
addScene(CamCalibDbProj_t * calibproj,const char * main_scene,const char * sub_scene,CamCalibDbV2Context_t * calib)149 int RkAiqSceneManager::addScene(CamCalibDbProj_t *calibproj,
150 const char *main_scene, const char *sub_scene,
151 CamCalibDbV2Context_t *calib) {
152 return 0;
153 }
154
155 CamCalibDbV2Context_t
refToScene(CamCalibDbProj_t * calibproj,const char * main_scene,const char * sub_scene)156 RkAiqSceneManager::refToScene(CamCalibDbProj_t *calibproj,
157 const char *main_scene, const char *sub_scene) {
158 CamCalibDbV2Context_t ctx;
159 CamCalibMainSceneList_t *main_list = nullptr;
160 CamCalibSubSceneList_t *sub_list = nullptr;
161 void* dst_calib = nullptr;
162 int main_list_len = -1;
163 int sub_list_len = -1;
164 int curr_main_scene = 0;
165 int curr_sub_scene = 0;
166
167 if (!calibproj) {
168 printf("No avaliable CamCalibDbProj loadded!\n");
169 return ctx;
170 }
171
172 main_list = calibproj->main_scene;
173 main_list_len = calibproj->main_scene_len;
174 memset(&ctx, 0, sizeof(CamCalibDbV2Context_t));
175
176 if (!main_list || main_list_len < 1) {
177 printf("No avaliable main scene for %s!\n", main_scene);
178 return ctx;
179 }
180
181 // Find main scene
182 for (curr_main_scene = 0; curr_main_scene < main_list_len;
183 curr_main_scene++) {
184 if (0 == strcmp(main_list[curr_main_scene].name, main_scene)) {
185 // Found what we want, and this must be the only one.
186 sub_list = main_list[curr_main_scene].sub_scene;
187 sub_list_len = main_list[curr_main_scene].sub_scene_len;
188 break;
189 }
190 }
191
192 if (!sub_list || sub_list_len < 1) {
193 printf("No avaliable sub scene!\n");
194 return ctx;
195 }
196
197 // Find sub scene
198 for (curr_sub_scene = 0; curr_sub_scene < sub_list_len; curr_sub_scene++) {
199 if (0 != strcmp(sub_list[curr_sub_scene].name, sub_scene)) {
200 // Not what we want
201 continue;
202 }
203 dst_calib = calibdbv2_get_scene_ptr(&sub_list[curr_sub_scene]);
204 ctx.calib_scene = (char*)(dst_calib);
205 ctx.sensor_info = &calibproj->sensor_calib;
206 ctx.module_info = &calibproj->module_calib;
207 ctx.sys_cfg = &calibproj->sys_static_cfg;
208
209 return ctx;
210 }
211
212 printf("Can't find scene:[%s]/[%s]!\n", main_scene, sub_scene);
213
214 return ctx;
215 }
216
findMainScene(cJSON * base_json,const char * name)217 cJSON *RkAiqSceneManager::findMainScene(cJSON *base_json, const char *name) {
218 cJSON *json_item = NULL;
219 cJSON *found_main_json = NULL;
220 cJSON *main_scene_json = NULL;
221
222 if (!base_json) {
223 XCAM_LOG_ERROR("input base json is invalid!\n");
224 return NULL;
225 }
226
227 main_scene_json = cJSONUtils_GetPointer(base_json, "/main_scene");
228 if (!main_scene_json) {
229 XCAM_LOG_ERROR("invalid main scene!\n");
230 return NULL;
231 }
232
233 int main_scene_sum = cJSON_GetArraySize(main_scene_json);
234 if (main_scene_sum <= 0) {
235 XCAM_LOG_ERROR("invalid main scene len!\n");
236 return NULL;
237 }
238
239 json_item = main_scene_json->child;
240
241 for (int i = 0; i <= (main_scene_sum - 1); ++i) {
242 if (json_item) {
243 char *name_str = cJSON_GetObjectItem(json_item, "name")->valuestring;
244 if (name_str && strstr(name_str, name)) {
245 found_main_json = json_item;
246 break;
247 }
248 }
249 json_item = json_item->next;
250 }
251
252 return found_main_json;
253 }
254
findSubScene(cJSON * main_json,const char * name)255 cJSON *RkAiqSceneManager::findSubScene(cJSON *main_json, const char *name) {
256 cJSON *json_item = NULL;
257 cJSON *found_sub_json = NULL;
258 cJSON *sub_scene_json = NULL;
259
260 if (!main_json) {
261 XCAM_LOG_ERROR("input main scene json is invalid!\n");
262 return NULL;
263 }
264
265 sub_scene_json = cJSONUtils_GetPointer(main_json, "/sub_scene");
266 if (!sub_scene_json) {
267 XCAM_LOG_ERROR("invalid sub scene!\n");
268 return NULL;
269 }
270
271 int sub_scene_sum = cJSON_GetArraySize(sub_scene_json);
272 if (sub_scene_sum <= 0) {
273 XCAM_LOG_ERROR("invalid main scene len!\n");
274 return NULL;
275 }
276
277 json_item = sub_scene_json->child;
278
279 for (int i = 0; i < sub_scene_sum; ++i) {
280 if (json_item) {
281 char *name_str = cJSON_GetObjectItem(json_item, "name")->valuestring;
282 if (name_str && strstr(name_str, name)) {
283 found_sub_json = json_item;
284 break;
285 }
286 }
287 json_item = json_item->next;
288 }
289
290 return found_sub_json;
291 }
292
findSubScene(cJSON * json,const char * main_scene,const char * sub_scene)293 cJSON *RkAiqSceneManager::findSubScene(cJSON *json, const char *main_scene,
294 const char *sub_scene) {
295 return findSubScene(findMainScene(json, main_scene), sub_scene);
296 }
297
mergeSubMultiScene(cJSON * sub_scene_list,cJSON * full_param,bool skip)298 cJSON *RkAiqSceneManager::mergeSubMultiScene(cJSON *sub_scene_list,
299 cJSON* full_param, bool skip) {
300 cJSON *json_item = NULL;
301 cJSON *new_item = NULL;
302 int sub_scene_sum = 0;
303 int i = 0;
304
305 if (!sub_scene_list || !full_param) {
306 XCAM_LOG_ERROR("input base json is invalid!\n");
307 return NULL;
308 }
309
310 // need skip first full param scene
311 if (cJSON_GetArraySize(sub_scene_list) <= skip) {
312 XCAM_LOG_ERROR("invalid main scene len!\n");
313 return NULL;
314 }
315
316 json_item = sub_scene_list->child;
317
318 sub_scene_sum = cJSON_GetArraySize(sub_scene_list);
319 for (i = 0; i < sub_scene_sum; i++) {
320 if (json_item) {
321 cJSON* temp_item = json_item;
322 json_item = json_item->next;
323 // skip the full param scene
324 if (i == 0 && skip) {
325 continue;
326 }
327 new_item = cJSON_Duplicate(full_param, 1);
328 new_item = cJSONUtils_MergePatch(new_item, temp_item);
329 cJSON_ReplaceItemInArray(sub_scene_list, i, new_item);
330 } else {
331 break;
332 }
333 }
334 return sub_scene_list;
335 }
336
mergeMainMultiScene(cJSON * main_scene_list)337 cJSON *RkAiqSceneManager::mergeMainMultiScene(cJSON *main_scene_list) {
338 cJSON *json_item = NULL;
339 cJSON *first_sub_scene_list = NULL;
340 cJSON *main_first = NULL;
341 cJSON *full_param = NULL;
342
343 if (!main_scene_list) {
344 XCAM_LOG_ERROR("input main scene list json is invalid!\n");
345 return NULL;
346 }
347
348 if (cJSON_GetArraySize(main_scene_list) <= 0) {
349 XCAM_LOG_ERROR("invalid main scene len!\n");
350 return NULL;
351 }
352
353 main_first = cJSON_GetArrayItem(main_scene_list, 0);
354 first_sub_scene_list = cJSONUtils_GetPointer(main_first, "/sub_scene");
355
356 if (cJSON_GetArraySize(first_sub_scene_list) <= 0) {
357 XCAM_LOG_ERROR("invalid sub scene len!\n");
358 return NULL;
359 }
360
361 full_param = cJSON_GetArrayItem(first_sub_scene_list, 0);
362
363 if (!full_param) {
364 XCAM_LOG_ERROR("invalid full param scene!\n");
365 return NULL;
366 }
367
368 json_item = main_scene_list->child;
369
370 int main_scene_sum = cJSON_GetArraySize(main_scene_list);
371 for (int i = 0; i < main_scene_sum; i++) {
372 // need skip first main scene's sub scene
373 cJSON *sub_scene_list = cJSONUtils_GetPointer(json_item, "/sub_scene");
374 if (json_item && sub_scene_list) {
375 mergeSubMultiScene(sub_scene_list, full_param, i == 0);
376 }
377 json_item = json_item->next;
378 }
379
380 return main_scene_list;
381 }
382
mergeMultiSceneIQ(cJSON * base_json)383 cJSON *RkAiqSceneManager::mergeMultiSceneIQ(cJSON *base_json) {
384 cJSON *main_scene_list_json = NULL;
385
386 // 1. foreach every sub scene.
387 // 2. merge every sub scene to base scene.
388 // 3. replace sub scene with new json.
389 if (!base_json) {
390 XCAM_LOG_ERROR("input base json is invalid!\n");
391 return NULL;
392 }
393
394 main_scene_list_json = cJSONUtils_GetPointer(base_json, "/main_scene");
395 if (!main_scene_list_json) {
396 XCAM_LOG_ERROR("invalid main scene!\n");
397 return NULL;
398 }
399
400 if (cJSON_GetArraySize(main_scene_list_json) <= 0) {
401 XCAM_LOG_ERROR("invalid main scene len!\n");
402 return NULL;
403 }
404
405 if (!mergeMainMultiScene(main_scene_list_json)) {
406 return NULL;
407 }
408
409 return base_json;
410 }
411
createSceneCalib(CamCalibDbProj_t * calibproj,const char * main_scene,const char * sub_scene)412 CamCalibDbV2Context_t* RkAiqSceneManager::createSceneCalib(
413 CamCalibDbProj_t* calibproj,
414 const char* main_scene,
415 const char* sub_scene) {
416 CamCalibDbV2Context_t *calib = NULL;
417 CamCalibDbV2Context_t* new_calib = NULL;
418 char* json_buff = NULL;
419 cJSON* root_json = NULL;
420 cJSON* base_json = NULL;
421 cJSON* diff_json = NULL;
422 cJSON* scene_json = NULL;
423 cJSON* calib_json = NULL;
424 j2s_ctx ctx;
425 int ret = -1;
426
427 #if defined(ISP_HW_V20)
428 CamCalibDbV2ContextIsp20_t *calib_scene = new CamCalibDbV2ContextIsp20_t;
429 #elif defined(ISP_HW_V21)
430 CamCalibDbV2ContextIsp21_t *calib_scene = new CamCalibDbV2ContextIsp21_t;
431 #elif defined(ISP_HW_V30)
432 CamCalibDbV2ContextIsp30_t *calib_scene = new CamCalibDbV2ContextIsp30_t;
433 #elif defined(ISP_HW_V32) || defined(ISP_HW_V32_LITE)
434 CamCalibDbV2ContextIsp32_t *calib_scene = new CamCalibDbV2ContextIsp32_t;
435 #else
436 #error "WRONG ISP_HW_VERSION, ONLY SUPPORT V20 AND V21 AND V30 NOW !"
437 #endif
438
439 j2s_init(&ctx);
440 json_buff = j2s_dump_root_struct(&ctx, calibproj);
441
442 if (!json_buff) {
443 XCAM_LOG_ERROR("create CamCalibDbProj json failed.");
444 return NULL;
445 }
446
447 root_json = cJSON_Parse(json_buff);
448 if (!root_json) {
449 XCAM_LOG_ERROR("create root json failed.");
450 goto error;
451 }
452
453 base_json = findSubScene(root_json, "normal", "day");
454 diff_json = findSubScene(root_json, main_scene, sub_scene);
455
456 if (!base_json || !diff_json) {
457 XCAM_LOG_ERROR("find sub scene json failed.");
458 goto error;
459 }
460
461 scene_json = cJSONUtils_MergePatch(base_json, diff_json);
462 if (!scene_json) {
463 XCAM_LOG_ERROR("merge sub scene json failed.");
464 goto error;
465 }
466
467 #if defined(ISP_HW_V20)
468 calib_json = cJSONUtils_GetPointer(scene_json, "scene_isp20");
469 #elif defined(ISP_HW_V21)
470 calib_json = cJSONUtils_GetPointer(scene_json, "scene_isp21");
471 #elif defined(ISP_HW_V30)
472 calib_json = cJSONUtils_GetPointer(scene_json, "scene_isp30");
473 #elif defined(ISP_HW_V32) || defined(ISP_HW_V32_LITE)
474 calib_json = cJSONUtils_GetPointer(scene_json, "scene_isp32");
475 #else
476 #error "WRONG ISP_HW_VERSION, ONLY SUPPORT V20 AND V21 AND V30 NOW !"
477 #endif
478
479 calib = RkAiqCalibDbV2::CalibV2Alloc();
480 ret = j2s_json_to_struct(&ctx, calib_json,
481 calibdbv2_get_scene_ctx_struct_name(calib),
482 calib_scene);
483 if (ret) {
484 XCAM_LOG_ERROR("merge sub scene json failed.");
485 goto error;
486 }
487
488 calib->module_info = &calibproj->module_calib;
489 calib->module_info_len = 1;
490 calib->sensor_info = &calibproj->sensor_calib;
491 calib->sensor_info_len = 1;
492 calib->sys_cfg = &calibproj->sys_static_cfg;
493 calib->sys_cfg_len = 1;
494 calib->calib_scene = (char*)calib_scene;
495
496 new_calib = calib;
497
498 error:
499 if (json_buff) {
500 free(json_buff);
501 }
502
503 if (root_json) {
504 cJSON_Delete(root_json);
505 }
506
507 j2s_deinit(&ctx);
508
509 return new_calib;
510 }
511
512 } // namespace RkCam
513