xref: /OK3568_Linux_fs/external/camera_engine_rkaiq/rkaiq/tools/j2s4b/src/j2s4b/BinRecord.cpp (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 #include "BinRecord.hpp"
2 
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <sys/fcntl.h>
7 #include <sys/stat.h>
8 #include <unistd.h>
9 
10 // #define DEBUG
11 
collectBinMap()12 int BinMapLoader::collectBinMap() {
13   uint8_t *data = struct_buffer;
14   size_t len = buffer_size;
15   size_t map_len = *(size_t *)(data + (len - sizeof(size_t)));
16   size_t map_offset = *(size_t *)(data + (len - sizeof(size_t) * 2));
17   size_t map_index = 0;
18   map_index_t *map_addr = NULL;
19   block_count = map_len;
20 
21   map_addr = (map_index_t *)(data + map_offset);
22 
23   block_vec.insert(block_vec.end(), data,
24                    data + (uint64_t)map_addr[0].ptr_offset);
25 
26   for (map_index = 0; map_index < map_len; map_index++) {
27     map_index_t tmap = (map_addr[map_index]);
28     map_vec.insert(map_vec.end(), (uint8_t *)&tmap,
29                    (uint8_t *)&tmap + sizeof(map_index_t));
30 
31     if (buffer_map[(uint64_t)tmap.ptr_offset]) {
32 #ifdef DEBUG
33       printf("skip:[%zu][%zu]!\n", map_index, (uint64_t)tmap.ptr_offset);
34 #endif
35       continue;
36     } else {
37       uint8_t *block_data = (uint64_t)tmap.ptr_offset + data;
38       buffer_map[(uint64_t)tmap.ptr_offset] = block_data;
39       uint64_t block_size = (uint64_t)tmap.len;
40       if (!block_data || block_size <= 0) {
41         printf("reduce error\n");
42         exit(0);
43       }
44       block_vec.insert(block_vec.end(), block_data, block_data + block_size);
45     }
46   }
47 
48   return 0;
49 }
50 
genBinary(void * buffer,size_t buffer_size)51 int BinMapLoader::genBinary(void *buffer, size_t buffer_size) {
52   if (buffer_size < block_vec.size() + map_vec.size()) {
53     printf("[BIN] buffer too small!\n");
54     return -1;
55   }
56 
57   size_t map_offset = block_vec.size();
58   size_t map_len = map_vec.size() / sizeof(map_index_t);
59   size_t file_size = (block_vec.size() + map_vec.size() + sizeof(size_t) * 2);
60 
61   memcpy(buffer, &block_vec[0], block_vec.size());
62   memcpy((uint8_t*)buffer + block_vec.size(), &map_vec[0], map_vec.size());
63   memcpy((uint8_t*)buffer + block_vec.size() + map_vec.size(), &map_offset,
64          sizeof(size_t));
65   memcpy((uint8_t*)buffer + block_vec.size() + map_vec.size() + sizeof(size_t),
66          &map_len, sizeof(map_len));
67 
68 #ifdef DEBUG
69   printf("[BIN] file size:%ld, %ld, %ld\n", file_size, block_vec.size(),
70          map_vec.size());
71 #endif
72 
73   return file_size;
74 }
75 
dumpMap()76 int BinMapLoader::dumpMap() {
77   size_t curr_index = 0;
78 
79   for (curr_index = 0; curr_index < block_count; curr_index++) {
80     map_index_t *temp_item =
81         (map_index_t *)&map_vec[curr_index * sizeof(map_index_t)];
82 #ifdef DEBUG
83     printf("[%ld]---dst:%ld-", curr_index, (uint64_t)temp_item->dst_offset);
84     printf("ptr:%ld-", (uint64_t)temp_item->ptr_offset);
85     printf("len:%ld\n", temp_item->len);
86 #endif
87 
88     dst_map[(uint64_t)temp_item->dst_offset] = (void *)0xfffff;
89   }
90 
91   return 0;
92 }
93 
parseBinStructMap(uint8_t * data,size_t len)94 int BinMapLoader::parseBinStructMap(uint8_t *data, size_t len) {
95   size_t map_len = *(size_t *)(data + (len - sizeof(size_t)));
96   size_t map_offset = *(size_t *)(data + (len - sizeof(size_t) * 2));
97   size_t map_index = 0;
98   map_index_t *map_addr = NULL;
99 
100   map_addr = (map_index_t *)(data + map_offset);
101 
102   for (map_index = 0; map_index < map_len; map_index++) {
103     map_index_t tmap = (map_addr[map_index]);
104     void **dst_obj_addr = (void **)(data + (size_t)tmap.dst_offset);
105     *dst_obj_addr = data + (uintptr_t)tmap.ptr_offset;
106 #ifdef DEBUG
107     printf("ori[%ld]---dst:%ld-", map_index, (uint64_t)tmap.dst_offset);
108     printf("ptr:%ld-", (uint64_t)tmap.ptr_offset);
109     printf("len:%ld\n", tmap.len);
110 #endif
111   }
112 
113   return 0;
114 }
115 
compareBinStruct(map_index_t * binstruct1,map_index_t * binstruct2)116 int BinMapLoader::compareBinStruct(map_index_t *binstruct1,
117                                    map_index_t *binstruct2) {
118   if (!binstruct1 || !binstruct2) {
119     return -1;
120   }
121 
122   if (binstruct1->len != binstruct2->len) {
123     return -1;
124   }
125 
126   if (binstruct1->ptr_offset == binstruct2->ptr_offset) {
127     return -1;
128   }
129 
130   void *first_obj = (uint64_t)binstruct1->ptr_offset + struct_buffer;
131   void *second_obj = (uint64_t)binstruct2->ptr_offset + struct_buffer;
132 
133   if (0 == memcmp(first_obj, second_obj, binstruct1->len)) {
134     same_block += binstruct1->len;
135 #ifdef DEBUG
136     printf("[BIN] found same block:%zu\n", same_block);
137 #endif
138     return 0;
139   }
140 
141   return -1;
142 }
143 
loadWholeFile(const char * fpath,size_t * fsize)144 void *BinMapLoader::loadWholeFile(const char *fpath, size_t *fsize) {
145   struct stat st;
146   void *buf;
147   int fd;
148 
149   if (!fpath || (0 != ::stat(fpath, &st))) {
150     printf("load bin file error!\n");
151     return NULL;
152   }
153 
154   fd = open(fpath, O_RDONLY);
155   if (fd < 0) {
156     printf("failed to open: '%s'\n", fpath);
157     return NULL;
158   }
159 
160   buf = malloc(st.st_size);
161   if (!buf) {
162     printf("read file oom!\n");
163     close(fd);
164     return NULL;
165   }
166 
167   if (read(fd, buf, st.st_size) != st.st_size) {
168     printf("failed to read: '%s'\n", fpath);
169     free(buf);
170     close(fd);
171     return NULL;
172   }
173 
174   *fsize = st.st_size;
175 
176   close(fd);
177 
178   return buf;
179 }
180 
saveFile(const char * fpath,void * buf,size_t file_size)181 int BinMapLoader::saveFile(const char *fpath, void *buf, size_t file_size) {
182   FILE *ofp = NULL;
183 
184   ofp = fopen(fpath, "wb+");
185   if (!ofp) {
186     printf("failed to open: '%s'\n", fpath);
187     return -1;
188   }
189 
190   fwrite(buf, 1, file_size, ofp);
191   fclose(ofp);
192 
193   return 0;
194 }
195 
loadFile(const char * filename)196 int BinMapLoader::loadFile(const char *filename) {
197   struct_buffer = (uint8_t *)loadWholeFile(filename, &buffer_size);
198   if (!struct_buffer) {
199     printf("[BIN] load file faild!\n");
200     return -1;
201   }
202 
203   return 0;
204 }
205 
suqeezBinMapOne()206 int BinMapLoader::suqeezBinMapOne() {
207   int curr_index = block_count - 1;
208 
209   for (curr_index = block_count - 1; curr_index > 0; curr_index--) {
210     map_index_t *map_item =
211         (map_index_t *)&map_vec[curr_index * sizeof(map_index_t)];
212     map_index_t *pre_item =
213         (map_index_t *)&map_vec[(curr_index - 1) * sizeof(map_index_t)];
214 
215     // skip the already modfied item
216     if (pre_item->ptr_offset >= map_item->ptr_offset) {
217       continue;
218     }
219 
220     if (map_item->len <= sizeof(void*) * 4) {
221       continue;
222     }
223 
224     map_index_t same_item;
225     memset(&same_item, 0, sizeof(map_index_t));
226     if (0 == findDuplicate(map_item, curr_index, &same_item)) {
227 #ifdef DEBUG
228       printf("[BIN] remove map:[%d]\n", curr_index);
229 #endif
230       removeMap(map_item, curr_index);
231       removeBlock(map_item, curr_index, &same_item);
232       return 0;
233     }
234   }
235 
236   return -1;
237 }
238 
suqeezBinMap(const char * fpath,uint8_t * buffer,size_t buffer_len)239 int BinMapLoader::suqeezBinMap(const char *fpath, uint8_t *buffer,
240                                size_t buffer_len) {
241   int ret = -1;
242   uint8_t *inp_buff = NULL;
243   uint8_t *out_buff = NULL;
244   size_t inp_size = 0;
245   size_t final_size = 0;
246 
247   if (buffer_len > MAX_IQBIN_SIZE) {
248     printf("[BIN] %s %d:iq binary too large!\n", __func__, __LINE__);
249     return -1;
250   }
251 
252   inp_buff = (uint8_t *)malloc(MAX_IQBIN_SIZE);
253   if (!inp_buff) {
254     printf("[BIN]%s %d:oom!\n", __func__, __LINE__);
255     return -1;
256     goto error;
257   }
258 
259   out_buff = (uint8_t *)malloc(MAX_IQBIN_SIZE);
260   if (!out_buff) {
261     printf("[BIN] %s %d:oom!\n", __func__, __LINE__);
262     goto error;
263   }
264 
265   memset(inp_buff, 0, MAX_IQBIN_SIZE);
266   memcpy(inp_buff, buffer, buffer_len);
267   inp_size = buffer_len;
268 
269   do {
270     BinMapLoader *loader = new BinMapLoader(inp_buff, inp_size);
271     loader->parseBinStructMap(inp_buff, inp_size);
272     loader->collectBinMap();
273     ret = loader->suqeezBinMapOne();
274     memset(out_buff, 0, MAX_IQBIN_SIZE);
275     final_size = loader->genBinary(out_buff, MAX_IQBIN_SIZE);
276     memset(inp_buff, 0, MAX_IQBIN_SIZE);
277     memcpy(inp_buff, out_buff, MAX_IQBIN_SIZE);
278     inp_size = final_size;
279 
280     if (ret != 0) {
281       loader->saveFile(fpath, out_buff, final_size);
282     }
283   } while (ret == 0);
284 
285 error:
286   if (inp_buff) {
287     free(inp_buff);
288   }
289 
290   if (out_buff) {
291     free(out_buff);
292   }
293 
294   return 0;
295 }
296 
findDuplicate(map_index_t * map_item,size_t map_index,map_index_t * ori_item)297 int BinMapLoader::findDuplicate(map_index_t *map_item, size_t map_index,
298                                 map_index_t *ori_item) {
299   size_t curr_index = 0;
300   if (map_index == 0) {
301     return -1;
302   }
303 
304   for (curr_index = 0; curr_index < block_count; curr_index++) {
305     map_index_t *item =
306         (map_index_t *)&map_vec[curr_index * sizeof(map_index_t)];
307 
308     if (0 == compareBinStruct(map_item, item)) {
309 #ifdef DEBUG
310       printf("[BIN][%ld]-", curr_index);
311       printf("duplicate-dst:%ld-", (uint64_t)item->dst_offset);
312       printf("ptr:%ld-", (uint64_t)item->ptr_offset);
313       printf("len:%ld\n", item->len);
314 #endif
315       *ori_item = *item;
316       return 0;
317     }
318     curr_index++;
319     if (curr_index >= map_index) {
320       return -1;
321     }
322   }
323 
324   return -1;
325 }
326 
removeBlock(map_index_t * map_item,size_t map_index,map_index_t * same_item)327 int BinMapLoader::removeBlock(map_index_t *map_item, size_t map_index,
328                               map_index_t *same_item) {
329   int curr_index = 0;
330   if (map_index == 0) {
331     return -1;
332   }
333 
334   uint64_t start_addr = (uint64_t)map_item->ptr_offset;
335   uint64_t end_addr = (uint64_t)map_item->ptr_offset + map_item->len;
336 
337 #ifdef DEBUG
338   printf("fix ptr after:%ld\n", (uint64_t)map_item->ptr_offset);
339 #endif
340 
341   for (curr_index = 0; curr_index < (int)block_count; curr_index++) {
342     map_index_t *temp_item =
343         (map_index_t *)&map_vec[curr_index * sizeof(map_index_t)];
344 
345     uint64_t curr_dst = (uint64_t)temp_item->dst_offset;
346     uint64_t curr_ptr = (uint64_t)temp_item->ptr_offset;
347     int64_t d_diff = curr_dst - start_addr;
348     int64_t p_diff = curr_ptr - start_addr;
349 
350     if (map_item->ptr_offset == temp_item->ptr_offset) {
351         if (map_item->dst_offset != temp_item->dst_offset)
352             temp_item->ptr_offset = same_item->ptr_offset;
353     }
354 
355 #if 0
356     printf("diff is [%ld], [%ld]\n", d_diff, p_diff);
357 #endif
358 
359     if (d_diff > 0) {
360       uint64_t new_offset = (uint64_t)temp_item->dst_offset - same_item->len;
361       temp_item->dst_offset = (void *)new_offset;
362     }
363 
364     if (p_diff > 0) {
365       uint64_t new_offset = (uint64_t)temp_item->ptr_offset - same_item->len;
366       temp_item->ptr_offset = (void *)new_offset;
367     }
368   }
369 
370   map_item->ptr_offset = same_item->ptr_offset;
371   map_item->len = 0;
372   block_vec.erase(block_vec.begin() + start_addr, block_vec.begin() + end_addr);
373 
374   return 0;
375 }
376 
removeMap(map_index_t * map_item,size_t map_index)377 int BinMapLoader::removeMap(map_index_t *map_item, size_t map_index) {
378   size_t curr_index = 0;
379   if (map_index == 0) {
380     return -1;
381   }
382 
383   uint64_t start_addr = (uint64_t)map_item->ptr_offset;
384   uint64_t end_addr = (uint64_t)map_item->ptr_offset + map_item->len;
385 
386   for (curr_index = 0; curr_index < block_count; curr_index++) {
387     map_index_t *temp_item =
388         (map_index_t *)&map_vec[curr_index * sizeof(map_index_t)];
389     if ((uint64_t)temp_item->dst_offset >= start_addr &&
390         (uint64_t)temp_item->dst_offset < end_addr) {
391 #ifdef DEBUG
392       printf("[BIN]remove the map->%d\n", curr_index);
393 #endif
394       map_vec.erase(map_vec.begin() + curr_index * sizeof(map_index_t),
395                     map_vec.begin() + (1 + curr_index) * sizeof(map_index_t));
396       block_count--;
397     }
398   }
399 
400   return 0;
401 }
402 
info()403 void BinMapLoader::info() {
404   printf("block info:[%zu]\n", block_vec.size());
405   printf("map info:[%zu]\n", map_vec.size());
406 }
407 
408