xref: /OK3568_Linux_fs/external/camera_engine_rkaiq/rkaiq/iq_parser_v2/j2s/j2s_utils.cpp (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  *  Copyright (c) 2020, Rockchip Electronics Co., Ltd
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  */
14 
15 #include "j2s.h"
16 #ifdef __ANDROID__
17 #if defined(ISP_HW_V20)
18 #include "j2s_generated_v20.h"
19 #elif defined(ISP_HW_V21)
20 #include "j2s_generated_v21.h"
21 #elif defined(ISP_HW_V30)
22 #include "j2s_generated_v30.h"
23 #elif defined(ISP_HW_V32)
24 #include "j2s_generated_v32.h"
25 #elif defined(ISP_HW_V32_LITE)
26 #include "j2s_generated_v32_lite.h"
27 #else
28 #error "Please define supported ISP version!!!, eg: -DISP_HW_V21"
29 #endif
30 #else
31 #ifdef COMPILE_TEMPLATE
32 #include ".j2s_generated.h"
33 #else
34 #include "j2s_generated.h"
35 #endif
36 #endif
37 
38 //#define J2S_USING_CACH
39 
40 #include <sys/stat.h>
41 
42 using namespace RkCam;
43 
44 typedef struct {
45     void* ptr;
46     bool freeable;
47 } j2s_ptr;
48 
49 typedef struct {
50     int num_data;
51     j2s_ptr* data;
52 } j2s_priv_data;
53 
j2s_alloc_data(j2s_ctx * ctx,size_t size)54 void* j2s_alloc_data(j2s_ctx* ctx, size_t size)
55 {
56     void* ptr = calloc(size, 1);
57     if (!ptr)
58         return NULL;
59 
60     if (j2s_add_data(ctx, ptr, false) < 0) {
61         free(ptr);
62         return NULL;
63     }
64 
65     return ptr;
66 }
67 
j2s_add_data(j2s_ctx * ctx,void * ptr,bool freeable)68 int j2s_add_data(j2s_ctx* ctx, void* ptr, bool freeable)
69 {
70     j2s_priv_data* priv;
71 
72     if (!ctx->priv)
73         ctx->priv = calloc(1, sizeof(j2s_priv_data));
74 
75     priv = (j2s_priv_data*)ctx->priv;
76     for (int i = 0; i < priv->num_data; i++) {
77         j2s_ptr* data = &priv->data[i];
78         if (data->ptr)
79             continue;
80 
81         data->ptr = ptr;
82         data->freeable = freeable;
83         return 0;
84     }
85 
86     priv->num_data++;
87     priv->data = (j2s_ptr*)realloc(priv->data, priv->num_data * sizeof(j2s_ptr));
88     if (!priv->data) {
89         ERR("failed to realloc\n");
90         priv->num_data = 0;
91         return -1;
92     }
93 
94     priv->data[priv->num_data - 1].ptr = ptr;
95     priv->data[priv->num_data - 1].freeable = freeable;
96     return 0;
97 }
98 
j2s_release_data(j2s_ctx * ctx,void * ptr)99 void j2s_release_data(j2s_ctx* ctx, void* ptr)
100 {
101     j2s_priv_data* priv = (j2s_priv_data*)ctx->priv;
102 
103 	void* free_ptr = ptr;
104     for (int i = 0; priv && i < priv->num_data; i++) {
105         j2s_ptr* data = &priv->data[i];
106         if (ptr != data->ptr)
107             continue;
108 
109         if (data->ptr && data->freeable) {
110             free(data->ptr);
111 			free_ptr = NULL;
112 		}
113         data->ptr = NULL;
114         //return;
115     }
116 
117     if (free_ptr)
118         free(ptr);
119 }
120 
j2s_read_file(const char * file,size_t * size)121 void* j2s_read_file(const char* file, size_t* size)
122 {
123     struct stat st;
124     void* buf;
125     int fd;
126 
127     DASSERT_MSG(file && !stat(file, &st), return NULL, "no such file: '%s'\n",
128         file ? file : "<null>");
129 
130     fd = open(file, O_RDONLY);
131     DASSERT_MSG(fd >= 0, return NULL, "failed to open: '%s'\n", file);
132 
133     buf = malloc(st.st_size + 1);
134     DASSERT(buf, return NULL);
135 
136     DBG("Read file: '%s'\n", file);
137 
138     if (read(fd, buf, st.st_size) != st.st_size) {
139         ERR("failed to read: '%s'\n", file);
140         free(buf);
141         close(fd);
142         return NULL;
143     }
144 
145     ((char*)buf)[st.st_size] = '\0';
146     *size = st.st_size;
147 
148     close(fd);
149     return buf;
150 }
151 
j2s_cache_file(const char * file)152 static char* j2s_cache_file(const char* file)
153 {
154 #ifdef J2S_USING_CACH
155     char cache_file[256];
156 
157     if (getenv("J2S_NO_CACHE")) {
158         DBG("Cache not allowed\n");
159         return NULL;
160     }
161 
162     strcpy(cache_file, getenv("J2S_CACHE") ? getenv("J2S_CACHE") : "/var/cache/j2s-cache");
163 
164     /* NULL for ctx cache file */
165     if (!file)
166         return strdup(cache_file);
167 
168     strcat(cache_file, "-");
169     strcat(cache_file, strrchr(file, '/') ? strrchr(file, '/') + 1 : file);
170 
171     for (int i = 0; cache_file[i]; i++) {
172         if (cache_file[i] == '.')
173             cache_file[i] = '-';
174     }
175 
176     return strdup(cache_file);
177 #else
178 	return NULL;
179 #endif
180 }
181 
j2s_cache_file_valid(const char * cache_file)182 static int j2s_cache_file_valid(const char* cache_file)
183 {
184     struct stat st;
185 
186     if (!cache_file || stat(cache_file, &st) < 0) {
187         DBG("invalid cache: '%s'\n", cache_file ?: "<NULL>");
188         return -1;
189     }
190 
191     if (getuid() != st.st_uid) {
192         DBG("invalid cache: '%s'\n", cache_file);
193         return -1;
194     }
195 
196     return 0;
197 }
198 
j2s_load_ctx_cache(j2s_ctx * ctx,const char * cache_file)199 static __attribute__((unused)) int j2s_load_ctx_cache(j2s_ctx* ctx,
200     const char* cache_file)
201 {
202     void *buf;
203     char* ptr;
204     size_t size;
205 
206     if (j2s_cache_file_valid(cache_file) < 0)
207         return -1;
208 
209     buf = j2s_read_file(cache_file, &size);
210     if (!buf || size <= sizeof(*ctx)) {
211         DBG("invalid cache: %s\n", cache_file ? cache_file : "nullptr");
212         goto err;
213     }
214 
215     DBG("Loading ctx cache: %s\n", cache_file ? cache_file : "nullptr");
216 
217     ptr = (char*)buf;
218 
219     *ctx = *(j2s_ctx*)ptr;
220     ctx->priv = NULL;
221     ptr += sizeof(*ctx);
222 
223     if (ctx->magic != J2S_MAGIC || ctx->num_obj != J2S_NUM_OBJ || ctx->num_struct != J2S_NUM_STRUCT || ctx->num_enum != J2S_NUM_ENUM || ctx->num_enum_value != J2S_NUM_ENUM_VALUE) {
224         DBG("invalid cache: %s\n", cache_file ? cache_file : "nullptr");
225         goto err;
226     }
227 
228     ctx->objs = (j2s_obj*)ptr;
229     ptr += ctx->num_obj * sizeof(*ctx->objs);
230 
231     ctx->structs = (j2s_struct*)ptr;
232     ptr += ctx->num_struct * sizeof(*ctx->structs);
233 
234     ctx->enums = (j2s_enum*)ptr;
235     ptr += ctx->num_enum * sizeof(*ctx->enums);
236 
237     ctx->enum_values = (j2s_enum_value*)ptr;
238     ptr += ctx->num_enum_value * sizeof(*ctx->enum_values);
239 
240     if (ptr != (char*)buf + size) {
241         DBG("invalid cache: %s\n", cache_file ? cache_file : "nullptr");
242         goto err;
243     }
244 
245     if (j2s_add_data(ctx, buf, true) < 0)
246         goto err;
247 
248     return 0;
249 err:
250     j2s_deinit(ctx);
251     free(buf);
252     return -1;
253 }
254 
j2s_save_ctx_cache(j2s_ctx * ctx,const char * cache_file)255 static __attribute__((unused)) void j2s_save_ctx_cache(j2s_ctx* ctx,
256     const char* cache_file)
257 {
258     int fd;
259     ssize_t bytes_written = 0;
260 
261     if (!cache_file)
262         return;
263 
264     fd = creat(cache_file, S_IRUSR | S_IWUSR);
265     if (fd < 0) {
266         DBG("failed to create: '%s'\n", cache_file);
267         return;
268     }
269 
270     DBG("Saving ctx cache: '%s'\n", cache_file);
271 
272     ctx->num_desc = 0;
273 
274     bytes_written = write(fd, ctx, sizeof(*ctx));
275     bytes_written = write(fd, ctx->objs, ctx->num_obj * sizeof(*ctx->objs));
276     bytes_written = write(fd, ctx->structs, ctx->num_struct * sizeof(*ctx->structs));
277     bytes_written = write(fd, ctx->enums, ctx->num_enum * sizeof(*ctx->enums));
278     bytes_written = write(fd, ctx->enum_values, ctx->num_enum_value * sizeof(*ctx->enum_values));
279 
280     close(fd);
281 }
282 
j2s_init(j2s_ctx * ctx)283 void j2s_init(j2s_ctx* ctx)
284 {
285     DBG("J2S version: %s\n", J2S_VERSION);
286 
287 #ifdef J2S_ENABLE_DESC
288     _j2s_init(ctx);
289 #else
290     char* cache_file = j2s_cache_file(NULL);
291 
292     if (j2s_load_ctx_cache(ctx, cache_file) < 0) {
293         _j2s_init(ctx);
294 #if 0
295 		FILE* fp = NULL;
296 		size_t total = 0;
297 		size_t wr_size = 0;
298 		fp = fopen("j2s_code2bin.bin","wb+");
299 
300 		size_t data_size = 0;
301 		data_size = sizeof(j2s_obj) * ctx->num_obj;
302 		wr_size = fwrite(ctx->objs, data_size , 1, fp);
303 		total += data_size;
304 		printf("write objs size: %zu, expected: %zu\n", wr_size * data_size, data_size);
305 
306 		data_size = sizeof(j2s_struct) * ctx->num_struct;
307 		wr_size = fwrite(ctx->structs, data_size , 1, fp);
308 		total += data_size;
309 		printf("write structs size: %zu, expected: %zu\n", wr_size * data_size, data_size);
310 
311 		data_size = sizeof(j2s_enum) * ctx->num_enum;
312 		wr_size = fwrite(ctx->enums, data_size , 1, fp);
313 		total += data_size;
314 		printf("write enums size: %zu, expected: %zu\n", wr_size * data_size, data_size);
315 
316 		data_size = sizeof(j2s_enum_value) * ctx->num_enum_value;
317 		wr_size = fwrite(ctx->enum_values, data_size , 1, fp);
318 		total += data_size;
319 		printf("write enum_valuses size: %zu, expected: %zu\n", wr_size * data_size, data_size);
320 
321 		printf("write total size: %zu\n", total);
322 
323 		fclose(fp);
324 #endif
325         j2s_save_ctx_cache(ctx, cache_file);
326     }
327 
328     if (cache_file)
329         free(cache_file);
330 #endif
331 
332     ctx->manage_data = true;
333 }
334 
j2s_camgroup_init(j2s_ctx * ctx)335 void j2s_camgroup_init(j2s_ctx* ctx)
336 {
337     DBG("J2S version: %s\n", J2S_VERSION);
338 
339     _j2s_init(ctx);
340 	// CamCalibDbProj_t always be followed by CamCalibDbGroup_t,
341 	// this was decided by the definition sequence in RkAiqCalibDbTypesV2
342 	ctx->root_index += 1;
343 
344     ctx->manage_data = true;
345 }
346 
j2s_deinit(j2s_ctx * ctx)347 void j2s_deinit(j2s_ctx* ctx)
348 {
349     j2s_priv_data* priv = (j2s_priv_data*)ctx->priv;
350 
351     for (int i = 0; priv && i < priv->num_data; i++) {
352         j2s_ptr* data = &priv->data[i];
353         if (!data->ptr || !data->freeable)
354             continue;
355 
356         /* Always free the cache file buf */
357         if (ctx->manage_data || (char*)data->ptr + sizeof(*ctx) == (char*)ctx->objs)
358             free(data->ptr);
359     }
360 
361     if (priv) {
362         if (priv->data)
363             free(priv->data);
364         free(priv);
365     }
366 }
367 
j2s_load_struct_cache(j2s_ctx * ctx,const char * cache_file,void * ptr,void * auth_data,int auth_size)368 int j2s_load_struct_cache(j2s_ctx* ctx, const char* cache_file, void* ptr,
369     void* auth_data, int auth_size)
370 {
371     int fd, ret = -1;
372 
373     if (j2s_cache_file_valid(cache_file) < 0)
374         return -1;
375 
376     fd = open(cache_file, O_RDONLY);
377     if (fd < 0) {
378         DBG("failed to open: '%s'\n", cache_file);
379         return -1;
380     }
381 
382     DBG("Loading struct cache: '%s'\n", cache_file);
383 
384     /* The cache file should start with auth data */
385     if (auth_data && auth_size) {
386         void* buf = malloc(auth_size);
387         if (!buf)
388             goto out;
389 
390         if (read(fd, buf, auth_size) != auth_size) {
391             free(buf);
392             goto out;
393         }
394 
395         if (memcmp(buf, auth_data, auth_size)) {
396             free(buf);
397             goto out;
398         }
399 
400         free(buf);
401     }
402 
403     if (j2s_root_struct_from_cache(ctx, fd, ptr) < 0)
404         goto out;
405 
406     /* Check end of file */
407     if (read(fd, &ret, 1) > 0)
408         goto out;
409 
410     DBG("Loaded struct cache: '%s'\n", cache_file);
411 
412     ret = 0;
413 out:
414     close(fd);
415     return ret;
416 }
417 
j2s_save_struct_cache(j2s_ctx * ctx,const char * cache_file,void * ptr,void * auth_data,int auth_size)418 void j2s_save_struct_cache(j2s_ctx* ctx, const char* cache_file, void* ptr,
419     void* auth_data, int auth_size)
420 {
421     int fd;
422     ssize_t bytes_written = 0;
423 
424     fd = creat(cache_file, S_IRUSR | S_IWUSR);
425     if (fd < 0) {
426         DBG("failed to create: '%s'\n", cache_file);
427         return;
428     }
429 
430     DBG("Saving struct cache: '%s'\n", cache_file);
431 
432     if (auth_data && auth_size)
433         bytes_written = write(fd, auth_data, auth_size);
434 
435     j2s_root_struct_to_cache(ctx, fd, ptr);
436 
437     close(fd);
438 }
439 
j2s_json_file_to_struct(j2s_ctx * ctx,const char * file,const char * name,void * ptr)440 int j2s_json_file_to_struct(j2s_ctx* ctx, const char* file, const char* name,
441     void* ptr)
442 {
443     char* cache_file = NULL;
444     struct stat st;
445     size_t size;
446     char* buf;
447     int ret = -1;
448 
449     DASSERT_MSG(file && !stat(file, &st), return -1, "no such file: '%s'\n",
450         file ? file : "<null>");
451 
452 #ifdef J2S_USING_CACH
453     cache_file = j2s_cache_file(file);
454 
455     /* Using the file stat as auth data */
456     if (!j2s_load_struct_cache(ctx, cache_file, ptr, &st, sizeof(st))) {
457         free(cache_file);
458         return 0;
459     }
460 #endif
461 
462     memset(ptr, 0, j2s_struct_size(ctx, ctx->root_index));
463 
464     buf = (char*)j2s_read_file(file, &size);
465     if (!buf)
466         goto out;
467 
468     DBG("Parse file: '%s', content:\n%s\n", file, buf);
469 
470     if (j2s_modify_struct(ctx, buf, name, ptr) < 0)
471         goto out;
472 
473 #ifdef J2S_USING_CACH
474     j2s_save_struct_cache(ctx, cache_file, ptr, &st, sizeof(st));
475 #endif
476     ret = 0;
477 out:
478 	if (cache_file)
479 		free(cache_file);
480     if (buf)
481         free(buf);
482     return ret;
483 }
484 
j2s_dump_struct(j2s_ctx * ctx,const char * name,void * ptr)485 char* j2s_dump_struct(j2s_ctx* ctx, const char* name, void* ptr)
486 {
487     cJSON *json, *item;
488     char* buf;
489 
490     DBG("Dump: %s\n", name ? name : "root struct");
491 
492     if (!name) {
493         json = j2s_root_struct_to_json(ctx, ptr);
494     } else {
495         json = j2s_struct_to_json(ctx, name, ptr);
496     }
497 
498     DASSERT(json, return NULL);
499 
500     if (ctx->dump_enums) {
501         item = j2s_enums_to_json(ctx);
502         if (item)
503             cJSON_AddItemToObject(json, "@enum", item);
504     }
505 
506     if (ctx->format_json) {
507         buf = cJSON_Print(json);
508     } else {
509         buf = cJSON_PrintUnformatted(json);
510     }
511 
512     cJSON_Delete(json);
513     return buf;
514 }
515 
j2s_modify_struct(j2s_ctx * ctx,const char * str,const char * name,void * ptr)516 int j2s_modify_struct(j2s_ctx* ctx, const char* str, const char* name,
517     void* ptr)
518 {
519     cJSON* json;
520     int ret = -1;
521 
522     json = cJSON_Parse(str);
523     DASSERT_MSG(json, return -1, "failed to parse: '%s'\n", str);
524 
525     DBG("Modify:\n%s\n", str);
526 
527     ret = j2s_json_to_struct(ctx, json, name, ptr);
528 
529     cJSON_Delete(json);
530     return ret;
531 }
532 
j2s_query_struct(j2s_ctx * ctx,const char * str,void * ptr)533 char* j2s_query_struct(j2s_ctx* ctx, const char* str, void* ptr)
534 {
535     cJSON* json;
536     char* buf;
537 
538     json = cJSON_Parse(str);
539     DASSERT_MSG(json, return NULL, "failed to parse: '%s'\n", str);
540 
541     DBG("Query:\n%s\n", str);
542 
543     if (j2s_json_from_root_struct(ctx, json, ptr) < 0) {
544         cJSON_Delete(json);
545         return NULL;
546     }
547 
548     if (ctx->format_json) {
549         buf = cJSON_Print(json);
550     } else {
551         buf = cJSON_PrintUnformatted(json);
552     }
553 
554     cJSON_Delete(json);
555     return buf;
556 }
557 
j2s_dump_template_struct(j2s_ctx * ctx,const char * name)558 char* j2s_dump_template_struct(j2s_ctx* ctx, const char* name)
559 {
560     cJSON *json, *item;
561     char* buf;
562 
563     DBG("Dump template: %s\n", name ? name : "root struct");
564 
565     if (!name) {
566         json = j2s_root_struct_to_template_json(ctx);
567     } else {
568         json = j2s_struct_to_template_json(ctx, name);
569     }
570 
571     DASSERT(json, return NULL);
572 
573     if (ctx->dump_enums) {
574         item = j2s_enums_to_json(ctx);
575         if (item)
576             cJSON_AddItemToObject(json, "@enum", item);
577     }
578 
579     if (ctx->format_json) {
580         buf = cJSON_Print(json);
581     } else {
582         buf = cJSON_PrintUnformatted(json);
583     }
584 
585     cJSON_Delete(json);
586     return buf;
587 }
588 
j2s_dump_structs(j2s_ctx * ctx,j2s_struct_info * info)589 char* j2s_dump_structs(j2s_ctx* ctx, j2s_struct_info* info)
590 {
591     cJSON *json, *item;
592     char* buf;
593 
594     if (!info || !info->name)
595         return NULL;
596 
597     DBG("Dump structs\n");
598 
599     json = cJSON_CreateObject();
600     DASSERT(json, return NULL);
601 
602     for (; info->name; info++) {
603         item = j2s_struct_to_json(ctx, info->name, info->ptr);
604         if (!item)
605             continue;
606 
607         cJSON_AddItemToObject(json, info->name, item);
608     }
609 
610     if (ctx->dump_enums) {
611         item = j2s_enums_to_json(ctx);
612         if (item)
613             cJSON_AddItemToObject(json, "@enum", item);
614     }
615 
616     if (ctx->format_json) {
617         buf = cJSON_Print(json);
618     } else {
619         buf = cJSON_PrintUnformatted(json);
620     }
621 
622     cJSON_Delete(json);
623     return buf;
624 }
625