xref: /aosp_15_r20/external/libopenapv/app/oapv_app_util.h (revision abb65b4b03b69e1d508d4d9a44dcf199df16e7c3)
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