1 /*
2 * Copyright (c) 2022 Samsung Electronics Co., Ltd.
3 * All Rights Reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * - Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * - Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * - Neither the name of the copyright owner, nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #ifndef _OAPV_APP_UTIL_H_
33 #define _OAPV_APP_UTIL_H_
34
35 #ifndef _CRT_SECURE_NO_WARNINGS
36 #define _CRT_SECURE_NO_WARNINGS
37 #endif
38
39 #include <stdlib.h>
40 #include <stdio.h>
41 #include <string.h>
42 #include <time.h>
43 #include <assert.h>
44 #include <math.h>
45 #include <stdarg.h>
46 #include <ctype.h>
47 #if LINUX
48 #include <signal.h>
49 #include <unistd.h>
50 #endif
51
52 #define VERBOSE_NONE 0
53 #define VERBOSE_ERROR 1
54 #define VERBOSE_SIMPLE 2
55 #define VERBOSE_FRAME 3
56
57 /* logging functions */
log_msg(char * filename,int line,const char * fmt,...)58 static void log_msg(char *filename, int line, const char *fmt, ...)
59 {
60 char str[1024] = { '\0' };
61 if(filename != NULL && line >= 0)
62 sprintf(str, "[%s:%d] ", filename, line);
63 va_list args;
64 va_start(args, fmt);
65 vsprintf(str + strlen(str), fmt, args);
66 va_end(args);
67 printf("%s", str);
68 }
69
log_line(char * pre)70 static void log_line(char *pre)
71 {
72 int i, len;
73 char str[128] = { '\0' };
74 const int chars = 80;
75 for(i = 0; i < 3; i++) {
76 str[i] = '=';
77 }
78 str[i] = '\0';
79
80 len = (pre == NULL) ? 0 : (int)strlen(pre);
81 if(len > 0) {
82 sprintf(str + 3, " %s ", pre);
83 len = (int)strlen(str);
84 }
85
86 for(i = len; i < chars; i++) {
87 str[i] = '=';
88 }
89 str[chars] = '\0';
90 printf("%s\n", str);
91 }
92
93 #if defined(__GNUC__)
94 #define __FILENAME__ \
95 (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
96
97 #define logerr(args...) \
98 { \
99 if(op_verbose >= VERBOSE_ERROR) { \
100 log_msg(NULL, -1, args); \
101 } \
102 }
103 #define logv2(args...) \
104 { \
105 if(op_verbose >= VERBOSE_SIMPLE) { \
106 log_msg(NULL, -1, args); \
107 } \
108 }
109 #define logv3(args...) \
110 { \
111 if(op_verbose >= VERBOSE_FRAME) { \
112 log_msg(NULL, -1, args); \
113 } \
114 }
115 #else
116 #define __FILENAME__ \
117 (strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__)
118 #define logerr(args, ...) \
119 { \
120 if(op_verbose >= VERBOSE_ERROR) { \
121 log_msg(NULL, -1, args, __VA_ARGS__); \
122 } \
123 }
124 #define logv2(args, ...) \
125 { \
126 if(op_verbose >= VERBOSE_SIMPLE) { \
127 log_msg(NULL, -1, args, __VA_ARGS__); \
128 } \
129 }
130 #define logv3(args, ...) \
131 { \
132 if(op_verbose >= VERBOSE_FRAME) { \
133 log_msg(NULL, -1, args, __VA_ARGS__); \
134 } \
135 }
136 #endif
137 #define logv2_line(pre) \
138 { \
139 if(op_verbose >= VERBOSE_SIMPLE) { \
140 log_line(pre); \
141 } \
142 }
143 #define logv3_line(pre) \
144 { \
145 if(op_verbose >= VERBOSE_FRAME) { \
146 log_line(pre); \
147 } \
148 }
149
150 /* assert function */
151 #include <assert.h>
152 #define assert_r(x) \
153 { \
154 if(!(x)) { \
155 assert(x); \
156 return; \
157 } \
158 }
159 #define assert_rv(x, r) \
160 { \
161 if(!(x)) { \
162 assert(x); \
163 return (r); \
164 } \
165 }
166 #define assert_g(x, g) \
167 { \
168 if(!(x)) { \
169 assert(x); \
170 goto g; \
171 } \
172 }
173 #define assert_gv(x, r, v, g) \
174 { \
175 if(!(x)) { \
176 assert(x); \
177 (r) = (v); \
178 goto g; \
179 } \
180 }
181
182 static int op_verbose = VERBOSE_SIMPLE;
183
184 /* Clocks */
185 #if defined(_WIN64) || defined(_WIN32)
186 #include <windows.h>
187
188 typedef DWORD oapv_clk_t;
189 #define OAPV_CLK_PER_SEC (1000)
190 #define OAPV_CLK_PER_MSEC (1)
191 #define OAPV_CLK_MAX ((oapv_clk_t)(-1))
192 #define oapv_clk_get() GetTickCount()
193
194 #elif __linux__ || __CYGWIN__ || __APPLE__
195 #include <time.h>
196 #include <sys/time.h>
197 typedef unsigned long oapv_clk_t;
198 #define OAPV_CLK_MAX ((oapv_clk_t)(-1))
199 #define OAPV_CLK_PER_SEC (10000)
200 #define OAPV_CLK_PER_MSEC (10)
oapv_clk_get(void)201 static oapv_clk_t oapv_clk_get(void)
202 {
203 oapv_clk_t clk;
204 struct timeval t;
205 gettimeofday(&t, NULL);
206 clk = t.tv_sec * 10000L + t.tv_usec / 100L;
207 return clk;
208 }
209
210 #else
211 #error THIS PLATFORM CANNOT SUPPORT CLOCK
212 #endif
213
oapv_clk_diff(oapv_clk_t t1,oapv_clk_t t2)214 static __inline oapv_clk_t oapv_clk_diff(oapv_clk_t t1, oapv_clk_t t2)
215 {
216 return (((t2) >= (t1)) ? ((t2) - (t1)) : ((OAPV_CLK_MAX - (t1)) + (t2)));
217 }
218
oapv_clk_from(oapv_clk_t from)219 static __inline oapv_clk_t oapv_clk_from(oapv_clk_t from)
220 {
221 oapv_clk_t now = oapv_clk_get();
222 return oapv_clk_diff(from, now);
223 }
224
oapv_clk_msec(oapv_clk_t clk)225 static __inline oapv_clk_t oapv_clk_msec(oapv_clk_t clk)
226 {
227 return ((oapv_clk_t)((clk + (OAPV_CLK_PER_MSEC / 2)) / OAPV_CLK_PER_MSEC));
228 }
229
oapv_clk_sec(oapv_clk_t clk)230 static __inline oapv_clk_t oapv_clk_sec(oapv_clk_t clk)
231 {
232 return ((oapv_clk_t)((clk + (OAPV_CLK_PER_SEC / 2)) / OAPV_CLK_PER_SEC));
233 }
234
235 #define CLIP_VAL(n, min, max) (((n) > (max)) ? (max) : (((n) < (min)) ? (min) : (n)))
236 #define ALIGN_VAL(val, align) ((((val) + (align) - 1) / (align)) * (align))
237
238 /* Function for atomic increament:
239 This function might need to modify according to O/S or CPU platform
240 */
atomic_inc(volatile int * pcnt)241 static int atomic_inc(volatile int *pcnt)
242 {
243 int ret;
244 ret = *pcnt;
245 ret++;
246 *pcnt = ret;
247 return ret;
248 }
249
250 /* Function for atomic decrement:
251 This function might need to modify according to O/S or CPU platform
252 */
atomic_dec(volatile int * pcnt)253 static int atomic_dec(volatile int *pcnt)
254 {
255 int ret;
256 ret = *pcnt;
257 ret--;
258 *pcnt = ret;
259 return ret;
260 }
261
262 /* Function to allocate memory for picture buffer:
263 This function might need to modify according to O/S or CPU platform
264 */
picbuf_alloc(int size)265 static void *picbuf_alloc(int size)
266 {
267 return malloc(size);
268 }
269
270 /* Function to free memory allocated for picture buffer:
271 This function might need to modify according to O/S or CPU platform
272 */
picbuf_free(void * p)273 static void picbuf_free(void *p)
274 {
275 if(p) {
276 free(p);
277 }
278 }
279
imgb_addref(oapv_imgb_t * imgb)280 static int imgb_addref(oapv_imgb_t *imgb)
281 {
282 assert_rv(imgb, OAPV_ERR_INVALID_ARGUMENT);
283 return atomic_inc(&imgb->refcnt);
284 }
285
imgb_getref(oapv_imgb_t * imgb)286 static int imgb_getref(oapv_imgb_t *imgb)
287 {
288 assert_rv(imgb, OAPV_ERR_INVALID_ARGUMENT);
289 return imgb->refcnt;
290 }
291
imgb_release(oapv_imgb_t * imgb)292 static int imgb_release(oapv_imgb_t *imgb)
293 {
294 int refcnt, i;
295 assert_rv(imgb, OAPV_ERR_INVALID_ARGUMENT);
296 refcnt = atomic_dec(&imgb->refcnt);
297 if(refcnt == 0) {
298 for(i = 0; i < OAPV_MAX_CC; i++) {
299 if(imgb->baddr[i])
300 picbuf_free(imgb->baddr[i]);
301 }
302 free(imgb);
303 }
304 return refcnt;
305 }
306
imgb_create(int w,int h,int cs)307 oapv_imgb_t *imgb_create(int w, int h, int cs)
308 {
309 int i, bd;
310 oapv_imgb_t *imgb;
311
312 imgb = (oapv_imgb_t *)malloc(sizeof(oapv_imgb_t));
313 if(imgb == NULL)
314 goto ERR;
315 memset(imgb, 0, sizeof(oapv_imgb_t));
316
317 bd = OAPV_CS_GET_BYTE_DEPTH(cs); /* byte unit */
318
319 imgb->w[0] = w;
320 imgb->h[0] = h;
321 switch(OAPV_CS_GET_FORMAT(cs)) {
322 case OAPV_CF_YCBCR400:
323 imgb->w[1] = imgb->w[2] = w;
324 imgb->h[1] = imgb->h[2] = h;
325 imgb->np = 1;
326 break;
327 case OAPV_CF_YCBCR420:
328 imgb->w[1] = imgb->w[2] = (w + 1) >> 1;
329 imgb->h[1] = imgb->h[2] = (h + 1) >> 1;
330 imgb->np = 3;
331 break;
332 case OAPV_CF_YCBCR422:
333 imgb->w[1] = imgb->w[2] = (w + 1) >> 1;
334 imgb->h[1] = imgb->h[2] = h;
335 imgb->np = 3;
336 break;
337 case OAPV_CF_YCBCR444:
338 imgb->w[1] = imgb->w[2] = w;
339 imgb->h[1] = imgb->h[2] = h;
340 imgb->np = 3;
341 break;
342 case OAPV_CF_YCBCR4444:
343 imgb->w[1] = imgb->w[2] = imgb->w[3] = w;
344 imgb->h[1] = imgb->h[2] = imgb->h[3] = h;
345 imgb->np = 4;
346 break;
347 case OAPV_CF_PLANAR2:
348 imgb->w[1] = w;
349 imgb->h[1] = h;
350 imgb->np = 2;
351 break;
352 default:
353 logv3("unsupported color format\n");
354 goto ERR;
355 }
356
357 for(i = 0; i < imgb->np; i++) {
358 // width and height need to be aligned to macroblock size
359 imgb->aw[i] = ALIGN_VAL(imgb->w[i], OAPV_MB_W);
360 imgb->s[i] = imgb->aw[i] * bd;
361 imgb->ah[i] = ALIGN_VAL(imgb->h[i], OAPV_MB_H);
362 imgb->e[i] = imgb->ah[i];
363
364 imgb->bsize[i] = imgb->s[i] * imgb->e[i];
365 imgb->a[i] = imgb->baddr[i] = picbuf_alloc(imgb->bsize[i]);
366 assert_g(imgb->a[i] != NULL, ERR);
367 memset(imgb->a[i], 0, imgb->bsize[i]);
368 }
369 imgb->cs = cs;
370 imgb->addref = imgb_addref;
371 imgb->getref = imgb_getref;
372 imgb->release = imgb_release;
373
374 imgb->addref(imgb); /* increase reference count */
375 return imgb;
376
377 ERR:
378 logerr("cannot create image buffer\n");
379 if(imgb) {
380 for(int i = 0; i < OAPV_MAX_CC; i++) {
381 if(imgb->a[i])
382 picbuf_free(imgb->a[i]);
383 }
384 free(imgb);
385 }
386 return NULL;
387 }
388
imgb_read(FILE * fp,oapv_imgb_t * img,int width,int height,int is_y4m)389 static int imgb_read(FILE *fp, oapv_imgb_t *img, int width, int height, int is_y4m)
390 {
391 int f_w, f_h;
392 unsigned char *p8;
393
394 /* handling Y4M frame header */
395 char t_buf[10];
396 if(is_y4m) {
397 if(6 != fread(t_buf, 1, 6, fp))
398 return -1;
399 if(memcmp(t_buf, "FRAME", 5)) {
400 logerr("Loss of framing in Y4M input data\n");
401 return -1;
402 }
403 if(t_buf[5] != '\n') {
404 logerr("Error parsing Y4M frame header\n");
405 return -1;
406 }
407 }
408
409 /* reading YUV format */
410 int chroma_format = OAPV_CS_GET_FORMAT(img->cs);
411 int bit_depth = OAPV_CS_GET_BIT_DEPTH(img->cs);
412 int w_shift = (chroma_format == OAPV_CF_YCBCR420) || ((chroma_format == OAPV_CF_YCBCR422) || (chroma_format == OAPV_CF_PLANAR2)) ? 1 : 0;
413 int h_shift = chroma_format == OAPV_CF_YCBCR420 ? 1 : 0;
414
415 if(bit_depth == 8) {
416 f_w = width;
417 f_h = height;
418 }
419 else if(bit_depth >= 10 && bit_depth <= 14) {
420 f_w = width * sizeof(short);
421 f_h = height;
422 }
423 else {
424 logerr("not supported bit-depth (%d)\n", bit_depth);
425 return -1;
426 }
427
428 p8 = (unsigned char *)img->a[0];
429 for(int j = 0; j < f_h; j++) {
430 if(fread(p8, 1, f_w, fp) != (unsigned)f_w) {
431 return -1;
432 }
433 p8 += img->s[0];
434 }
435
436 if(chroma_format == OAPV_CF_PLANAR2) {
437 p8 = (unsigned char *)img->a[1];
438 for(int j = 0; j < f_h; j++) {
439 if(fread(p8, 1, f_w, fp) != (unsigned)f_w) {
440 return -1;
441 }
442 p8 += img->s[1];
443 }
444 }
445 else if(chroma_format != OAPV_CF_YCBCR400) {
446 f_w = f_w >> w_shift;
447 f_h = f_h >> h_shift;
448
449 p8 = (unsigned char *)img->a[1];
450 for(int j = 0; j < f_h; j++) {
451 if(fread(p8, 1, f_w, fp) != (unsigned)f_w) {
452 return -1;
453 }
454 p8 += img->s[1];
455 }
456
457 p8 = (unsigned char *)img->a[2];
458 for(int j = 0; j < f_h; j++) {
459 if(fread(p8, 1, f_w, fp) != (unsigned)f_w) {
460 return -1;
461 }
462 p8 += img->s[2];
463 }
464 }
465
466 if(chroma_format == OAPV_CF_YCBCR4444) {
467 f_w = f_w >> w_shift;
468 f_h = f_h >> h_shift;
469
470 p8 = (unsigned char *)img->a[3];
471 for(int j = 0; j < f_h; j++) {
472 if(fread(p8, 1, f_w, fp) != (unsigned)f_w) {
473 return -1;
474 }
475 p8 += img->s[3];
476 }
477 }
478
479 return 0;
480 }
481
imgb_write(char * fname,oapv_imgb_t * imgb)482 static int imgb_write(char *fname, oapv_imgb_t *imgb)
483 {
484 unsigned char *p8;
485 int i, j, bd;
486 FILE *fp;
487
488 int chroma_format = OAPV_CS_GET_FORMAT(imgb->cs);
489 int bit_depth = OAPV_CS_GET_BIT_DEPTH(imgb->cs);
490
491 fp = fopen(fname, "ab");
492 if(fp == NULL) {
493 logerr("cannot open file = %s\n", fname);
494 return -1;
495 }
496 if(bit_depth == 8 && (chroma_format == OAPV_CF_YCBCR400 || chroma_format == OAPV_CF_YCBCR420 || chroma_format == OAPV_CF_YCBCR422 ||
497 chroma_format == OAPV_CF_YCBCR444 || chroma_format == OAPV_CF_YCBCR4444)) {
498 bd = 1;
499 }
500 else if(bit_depth >= 10 && bit_depth <= 14 && (chroma_format == OAPV_CF_YCBCR400 || chroma_format == OAPV_CF_YCBCR420 || chroma_format == OAPV_CF_YCBCR422 || chroma_format == OAPV_CF_YCBCR444 || chroma_format == OAPV_CF_YCBCR4444)) {
501 bd = 2;
502 }
503 else if(bit_depth >= 10 && chroma_format == OAPV_CF_PLANAR2) {
504 bd = 2;
505 }
506 else {
507 logerr("cannot support the color space\n");
508 fclose(fp);
509 return -1;
510 }
511
512 for(i = 0; i < imgb->np; i++) {
513 p8 = (unsigned char *)imgb->a[i] + (imgb->s[i] * imgb->y[i]) + (imgb->x[i] * bd);
514
515 for(j = 0; j < imgb->h[i]; j++) {
516 fwrite(p8, imgb->w[i] * bd, 1, fp);
517 p8 += imgb->s[i];
518 }
519 }
520
521 fclose(fp);
522 return 0;
523 }
524
imgb_cpy_plane(oapv_imgb_t * dst,oapv_imgb_t * src)525 static void imgb_cpy_plane(oapv_imgb_t *dst, oapv_imgb_t *src)
526 {
527 int i, j;
528 unsigned char *s, *d;
529 int numbyte = OAPV_CS_GET_BYTE_DEPTH(src->cs);
530
531 for(i = 0; i < src->np; i++) {
532 s = (unsigned char *)src->a[i];
533 d = (unsigned char *)dst->a[i];
534
535 for(j = 0; j < src->ah[i]; j++) {
536 memcpy(d, s, numbyte * src->aw[i]);
537 s += src->s[i];
538 d += dst->s[i];
539 }
540 }
541 }
542
imgb_cpy_shift_left_8b(oapv_imgb_t * dst,oapv_imgb_t * src,int shift)543 static void imgb_cpy_shift_left_8b(oapv_imgb_t *dst, oapv_imgb_t *src, int shift)
544 {
545 int i, j, k;
546
547 unsigned char *s;
548 short *d;
549
550 for(i = 0; i < dst->np; i++) {
551 s = (unsigned char *)src->a[i];
552 d = (short *)dst->a[i];
553
554 for(j = 0; j < src->ah[i]; j++) {
555 for(k = 0; k < src->aw[i]; k++) {
556 d[k] = (short)(s[k] << shift);
557 }
558 s = s + src->s[i];
559 d = (short *)(((unsigned char *)d) + dst->s[i]);
560 }
561 }
562 }
563
imgb_cpy_shift_right_8b(oapv_imgb_t * dst,oapv_imgb_t * src,int shift)564 static void imgb_cpy_shift_right_8b(oapv_imgb_t *dst, oapv_imgb_t *src, int shift)
565 {
566 int i, j, k, t0, add;
567
568 short *s;
569 unsigned char *d;
570
571 if(shift)
572 add = 1 << (shift - 1);
573 else
574 add = 0;
575
576 for(i = 0; i < dst->np; i++) {
577 s = (short *)src->a[i];
578 d = (unsigned char *)dst->a[i];
579
580 for(j = 0; j < src->ah[i]; j++) {
581 for(k = 0; k < src->aw[i]; k++) {
582 t0 = ((s[k] + add) >> shift);
583 d[k] = (unsigned char)(CLIP_VAL(t0, 0, 255));
584 }
585 s = (short *)(((unsigned char *)s) + src->s[i]);
586 d = d + dst->s[i];
587 }
588 }
589 }
590
imgb_cpy_shift_left(oapv_imgb_t * dst,oapv_imgb_t * src,int shift)591 static void imgb_cpy_shift_left(oapv_imgb_t *dst, oapv_imgb_t *src, int shift)
592 {
593 int i, j, k;
594
595 unsigned short *s;
596 unsigned short *d;
597
598 for(i = 0; i < dst->np; i++) {
599 s = (unsigned short *)src->a[i];
600 d = (unsigned short *)dst->a[i];
601
602 for(j = 0; j < src->h[i]; j++) {
603 for(k = 0; k < src->w[i]; k++) {
604 d[k] = (unsigned short)(s[k] << shift);
605 }
606 s = (unsigned short *)(((unsigned char *)s) + src->s[i]);
607 d = (unsigned short *)(((unsigned char *)d) + dst->s[i]);
608 }
609 }
610 }
611
imgb_cpy_shift_right(oapv_imgb_t * dst,oapv_imgb_t * src,int shift)612 static void imgb_cpy_shift_right(oapv_imgb_t *dst, oapv_imgb_t *src, int shift)
613 {
614 int i, j, k, t0, add;
615
616 int clip_min = 0;
617 int clip_max = 0;
618
619 unsigned short *s;
620 unsigned short *d;
621
622 if(shift)
623 add = 1 << (shift - 1);
624 else
625 add = 0;
626
627 clip_max = (1 << (OAPV_CS_GET_BIT_DEPTH(dst->cs))) - 1;
628
629 for(i = 0; i < dst->np; i++) {
630 s = (unsigned short *)src->a[i];
631 d = (unsigned short *)dst->a[i];
632
633 for(j = 0; j < src->h[i]; j++) {
634 for(k = 0; k < src->w[i]; k++) {
635 t0 = ((s[k] + add) >> shift);
636 d[k] = (CLIP_VAL(t0, clip_min, clip_max));
637 }
638 s = (unsigned short *)(((unsigned char *)s) + src->s[i]);
639 d = (unsigned short *)(((unsigned char *)d) + dst->s[i]);
640 }
641 }
642 }
643
imgb_cpy(oapv_imgb_t * dst,oapv_imgb_t * src)644 static void imgb_cpy(oapv_imgb_t *dst, oapv_imgb_t *src)
645 {
646 int i, bd_src, bd_dst;
647 bd_src = OAPV_CS_GET_BIT_DEPTH(src->cs);
648 bd_dst = OAPV_CS_GET_BIT_DEPTH(dst->cs);
649
650 if(src->cs == dst->cs) {
651 imgb_cpy_plane(dst, src);
652 }
653 else if(bd_src == 8 && bd_dst > 8) {
654 imgb_cpy_shift_left_8b(dst, src, bd_dst - bd_src);
655 }
656 else if(bd_src > 8 && bd_dst == 8) {
657 imgb_cpy_shift_right_8b(dst, src, bd_src - bd_dst);
658 }
659 else if(bd_src < bd_dst) {
660 imgb_cpy_shift_left(dst, src, bd_dst - bd_src);
661 }
662 else if(bd_src > bd_dst) {
663 imgb_cpy_shift_right(dst, src, bd_src - bd_dst);
664 }
665 else {
666 logerr("ERROR: unsupported image copy\n");
667 return;
668 }
669 for(i = 0; i < OAPV_MAX_CC; i++) {
670 dst->x[i] = src->x[i];
671 dst->y[i] = src->y[i];
672 dst->w[i] = src->w[i];
673 dst->h[i] = src->h[i];
674 dst->ts[i] = src->ts[i];
675 }
676 }
677
measure_psnr(oapv_imgb_t * org,oapv_imgb_t * rec,double psnr[4],int bit_depth)678 static void measure_psnr(oapv_imgb_t *org, oapv_imgb_t *rec, double psnr[4], int bit_depth)
679 {
680 double sum[4], mse[4];
681
682 if(bit_depth == 8) {
683 unsigned char *o, *r;
684 int i, j, k;
685
686 for(i = 0; i < org->np; i++) {
687 o = (unsigned char *)org->a[i];
688 r = (unsigned char *)rec->a[i];
689 sum[i] = 0;
690
691 for(j = 0; j < org->h[i]; j++) {
692 for(k = 0; k < org->w[i]; k++) {
693 sum[i] += (o[k] - r[k]) * (o[k] - r[k]);
694 }
695
696 o += org->s[i];
697 r += rec->s[i];
698 }
699 mse[i] = sum[i] / (org->w[i] * org->h[i]);
700 psnr[i] = (mse[i] == 0.0) ? 100. : fabs(10 * log10(((255 * 255) / mse[i])));
701 }
702 }
703 else {
704 /* more than 8bit, ex) 10bit */
705 unsigned short *o, *r;
706 int i, j, k;
707 int factor = 1 << (bit_depth - 8);
708 factor *= factor;
709 for(i = 0; i < org->np; i++) {
710 o = (unsigned short *)org->a[i];
711 r = (unsigned short *)rec->a[i];
712 sum[i] = 0;
713 for(j = 0; j < org->h[i]; j++) {
714 for(k = 0; k < org->w[i]; k++) {
715 if(OAPV_CS_GET_FORMAT(org->cs) == OAPV_CF_PLANAR2) {
716 sum[i] += (((int)o[k] - (int)r[k]) >> 6) * (((int)o[k] - (int)r[k]) >> 6);
717 }
718 else {
719 sum[i] += (o[k] - r[k]) * (o[k] - r[k]);
720 }
721 }
722 o = (unsigned short *)((unsigned char *)o + org->s[i]);
723 r = (unsigned short *)((unsigned char *)r + rec->s[i]);
724 }
725 mse[i] = sum[i] / (org->w[i] * org->h[i]);
726 psnr[i] = (mse[i] == 0.0) ? 100. : fabs(10 * log10(((255 * 255 * factor) / mse[i])));
727 }
728 }
729 }
730
write_data(char * fname,unsigned char * data,int size)731 static int write_data(char *fname, unsigned char *data, int size)
732 {
733 FILE *fp;
734
735 fp = fopen(fname, "ab");
736 if(fp == NULL) {
737 logerr("cannot open an writing file=%s\n", fname);
738 return -1;
739 }
740 fwrite(data, 1, size, fp);
741 fclose(fp);
742 return 0;
743 }
744
clear_data(char * fname)745 static int clear_data(char *fname)
746 {
747 FILE *fp;
748 fp = fopen(fname, "wb");
749 if(fp == NULL) {
750 logerr("cannot remove file (%s)\n", fname);
751 return -1;
752 }
753 fclose(fp);
754 return 0;
755 }
char_to_hex(char a)756 static unsigned char char_to_hex(char a)
757 {
758 unsigned char ret;
759
760 switch(a) {
761 case 'a':
762 case 'A':
763 ret = 10;
764 break;
765 case 'b':
766 case 'B':
767 ret = 11;
768 break;
769 case 'c':
770 case 'C':
771 ret = 12;
772 break;
773 case 'd':
774 case 'D':
775 ret = 13;
776 break;
777 case 'e':
778 case 'E':
779 ret = 14;
780 break;
781 case 'f':
782 case 'F':
783 ret = 15;
784 break;
785 default:
786 ret = (unsigned char)a - '0';
787 break;
788 }
789 return ret;
790 }
791
792 #endif /* _OAPV_APP_UTIL_H_ */
793