Modify parameter in imgage processing APIs to mm_util_image_h
[platform/core/multimedia/libmm-utility.git] / imgp / mm_util_imgp.c
1 /*
2  * libmm-utility
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: YoungHun Kim <yh8004.kim@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22 #include <gmodule.h>
23 #include <limits.h>
24 #include "mm_util_private.h"
25 #include "mm_util_imgp.h"
26 #include "mm_util_imgp_internal.h"
27
28 #define GEN_MASK(x) ((1<<(x))-1)
29 #define ROUND_UP_X(v, x) (((v) + GEN_MASK(x)) & ~GEN_MASK(x))
30 #define DIV_ROUND_UP_X(v, x) (((v) + GEN_MASK(x)) >> (x))
31 #define GST "gstcs"
32
33 typedef gboolean(*IMGPInfoFunc) (imgp_info_s *, const unsigned char *, unsigned char **, imgp_plugin_type_e);
34
35 static int __check_valid_picture_size(unsigned int width, unsigned int height)
36 {
37         if ((size_t)((width + 128) * (height + 128)) < (size_t)(INT_MAX/4))
38                 return MM_UTIL_ERROR_NONE;
39
40         return MM_UTIL_ERROR_INVALID_PARAMETER;
41 }
42
43 static gboolean __mm_gst_can_resize_format(mm_util_color_format_e color_format)
44 {
45         gboolean _bool = FALSE;
46
47         mm_util_debug("color_format [%d]", color_format);
48
49         switch (color_format) {
50         case MM_UTIL_COLOR_YUV420:
51         case MM_UTIL_COLOR_YUV422:
52         case MM_UTIL_COLOR_I420:
53         case MM_UTIL_COLOR_UYVY:
54         case MM_UTIL_COLOR_YUYV:
55         case MM_UTIL_COLOR_RGB16:
56         case MM_UTIL_COLOR_RGB24:
57         case MM_UTIL_COLOR_ARGB:
58         case MM_UTIL_COLOR_BGRA:
59         case MM_UTIL_COLOR_RGBA:
60         case MM_UTIL_COLOR_BGRX:
61                 _bool = TRUE;
62                 break;
63         default:
64                 mm_util_error("Not supported format");  //only not support NV12
65         }
66
67         return _bool;
68 }
69
70 static gboolean __mm_gst_can_rotate_format(mm_util_color_format_e color_format)
71 {
72         gboolean _bool = FALSE;
73
74         mm_util_debug("color_format [%d]", color_format);
75
76         switch (color_format) {
77         case MM_UTIL_COLOR_YUV420:
78         case MM_UTIL_COLOR_I420:
79         case MM_UTIL_COLOR_RGB24:
80         case MM_UTIL_COLOR_ARGB:
81         case MM_UTIL_COLOR_BGRA:
82         case MM_UTIL_COLOR_RGBA:
83                 _bool = TRUE;
84                 break;
85         default:
86                 mm_util_error("Not supported format");
87         }
88
89         return _bool;
90 }
91
92 static gboolean __mm_select_convert_plugin(mm_util_color_format_e src_format, mm_util_color_format_e dst_format)
93 {
94         gboolean _bool = FALSE;
95
96         mm_util_debug("src_format: %d, dst_format:%d", src_format, dst_format);
97
98         if (((src_format == MM_UTIL_COLOR_YUV420) && (dst_format == MM_UTIL_COLOR_NV12)) ||
99                 ((src_format == MM_UTIL_COLOR_YUV420) && (dst_format == MM_UTIL_COLOR_RGB16)) ||
100                 ((src_format == MM_UTIL_COLOR_YUV420) && (dst_format == MM_UTIL_COLOR_RGB24)) ||
101                 ((src_format == MM_UTIL_COLOR_YUV420) && (dst_format == MM_UTIL_COLOR_ARGB)) ||
102                 ((src_format == MM_UTIL_COLOR_YUV420) && (dst_format == MM_UTIL_COLOR_BGRA)) ||
103                 ((src_format == MM_UTIL_COLOR_YUV420) && (dst_format == MM_UTIL_COLOR_RGBA)) ||
104                 ((src_format == MM_UTIL_COLOR_YUV420) && (dst_format == MM_UTIL_COLOR_NV12_TILED)) ||
105
106                 ((src_format == MM_UTIL_COLOR_I420) && (dst_format == MM_UTIL_COLOR_NV12)) ||
107                 ((src_format == MM_UTIL_COLOR_I420) && (dst_format == MM_UTIL_COLOR_RGB16)) ||
108                 ((src_format == MM_UTIL_COLOR_I420) && (dst_format == MM_UTIL_COLOR_RGB24)) ||
109                 ((src_format == MM_UTIL_COLOR_I420) && (dst_format == MM_UTIL_COLOR_ARGB)) ||
110                 ((src_format == MM_UTIL_COLOR_I420) && (dst_format == MM_UTIL_COLOR_BGRA)) ||
111                 ((src_format == MM_UTIL_COLOR_I420) && (dst_format == MM_UTIL_COLOR_RGBA)) ||
112                 ((src_format == MM_UTIL_COLOR_I420) && (dst_format == MM_UTIL_COLOR_NV12_TILED)) ||
113
114                 ((src_format == MM_UTIL_COLOR_NV12) && (dst_format == MM_UTIL_COLOR_YUV420)) ||
115                 ((src_format == MM_UTIL_COLOR_NV12) && (dst_format == MM_UTIL_COLOR_I420)) ||
116                 ((src_format == MM_UTIL_COLOR_NV12) && (dst_format == MM_UTIL_COLOR_RGB16)) ||
117                 ((src_format == MM_UTIL_COLOR_NV12) && (dst_format == MM_UTIL_COLOR_RGB24)) ||
118                 ((src_format == MM_UTIL_COLOR_NV12) && (dst_format == MM_UTIL_COLOR_ARGB)) ||
119                 ((src_format == MM_UTIL_COLOR_NV12) && (dst_format == MM_UTIL_COLOR_BGRA)) ||
120                 ((src_format == MM_UTIL_COLOR_NV12) && (dst_format == MM_UTIL_COLOR_RGBA)) ||
121
122                 ((src_format == MM_UTIL_COLOR_UYVY) && (dst_format == MM_UTIL_COLOR_RGB16)) ||
123                 ((src_format == MM_UTIL_COLOR_UYVY) && (dst_format == MM_UTIL_COLOR_RGB24)) ||
124
125                 ((src_format == MM_UTIL_COLOR_YUYV) && (dst_format == MM_UTIL_COLOR_RGB16)) ||
126                 ((src_format == MM_UTIL_COLOR_YUYV) && (dst_format == MM_UTIL_COLOR_RGB24)) ||
127                 ((src_format == MM_UTIL_COLOR_YUYV) && (dst_format == MM_UTIL_COLOR_ARGB)) ||
128                 ((src_format == MM_UTIL_COLOR_YUYV) && (dst_format == MM_UTIL_COLOR_BGRA)) ||
129                 ((src_format == MM_UTIL_COLOR_YUYV) && (dst_format == MM_UTIL_COLOR_RGBA)) ||
130
131                 ((src_format == MM_UTIL_COLOR_RGB16) && (dst_format == MM_UTIL_COLOR_YUV420)) ||
132                 ((src_format == MM_UTIL_COLOR_RGB16) && (dst_format == MM_UTIL_COLOR_I420)) ||
133                 ((src_format == MM_UTIL_COLOR_RGB16) && (dst_format == MM_UTIL_COLOR_NV12)) ||
134
135                 ((src_format == MM_UTIL_COLOR_RGB24) && (dst_format == MM_UTIL_COLOR_YUV420)) ||
136                 ((src_format == MM_UTIL_COLOR_RGB24) && (dst_format == MM_UTIL_COLOR_I420)) ||
137                 ((src_format == MM_UTIL_COLOR_RGB24) && (dst_format == MM_UTIL_COLOR_NV12)) ||
138
139                 ((src_format == MM_UTIL_COLOR_ARGB) && (dst_format == MM_UTIL_COLOR_YUV420)) ||
140                 ((src_format == MM_UTIL_COLOR_ARGB) && (dst_format == MM_UTIL_COLOR_I420)) ||
141                 ((src_format == MM_UTIL_COLOR_ARGB) && (dst_format == MM_UTIL_COLOR_NV12)) ||
142
143                 ((src_format == MM_UTIL_COLOR_BGRA) && (dst_format == MM_UTIL_COLOR_YUV420)) ||
144                 ((src_format == MM_UTIL_COLOR_BGRA) && (dst_format == MM_UTIL_COLOR_I420)) ||
145                 ((src_format == MM_UTIL_COLOR_BGRA) && (dst_format == MM_UTIL_COLOR_NV12)) ||
146                 ((src_format == MM_UTIL_COLOR_RGBA) && (dst_format == MM_UTIL_COLOR_YUV420)) ||
147                 ((src_format == MM_UTIL_COLOR_RGBA) && (dst_format == MM_UTIL_COLOR_I420)) ||
148                 ((src_format == MM_UTIL_COLOR_RGBA) && (dst_format == MM_UTIL_COLOR_NV12)) ||
149                 ((src_format == MM_UTIL_COLOR_RGBA) && (dst_format == MM_UTIL_COLOR_RGB16)) ||
150
151                 ((src_format == MM_UTIL_COLOR_NV12_TILED) && (dst_format == MM_UTIL_COLOR_YUV420)) ||
152                 ((src_format == MM_UTIL_COLOR_NV12_TILED) && (dst_format == MM_UTIL_COLOR_I420)) ||
153                 ((src_format == MM_UTIL_COLOR_NV12_TILED) && (dst_format == MM_UTIL_COLOR_NV12)) ||
154                 ((src_format == MM_UTIL_COLOR_NV12_TILED) && (dst_format == MM_UTIL_COLOR_RGB16)) ||
155                 ((src_format == MM_UTIL_COLOR_NV12_TILED) && (dst_format == MM_UTIL_COLOR_RGB24)) ||
156                 ((src_format == MM_UTIL_COLOR_NV12_TILED) && (dst_format == MM_UTIL_COLOR_ARGB)) ||
157                 ((src_format == MM_UTIL_COLOR_NV12_TILED) && (dst_format == MM_UTIL_COLOR_BGRA)) ||
158                 ((src_format == MM_UTIL_COLOR_NV12_TILED) && (dst_format == MM_UTIL_COLOR_RGBA))) {
159
160                 _bool = TRUE;
161         }
162
163         return _bool;
164 }
165
166 static gboolean __mm_select_resize_plugin(mm_util_color_format_e _format)
167 {
168         gboolean _bool = FALSE;
169
170         mm_util_debug("_format: %d", _format);
171
172         if ((_format == MM_UTIL_COLOR_UYVY) || (_format == MM_UTIL_COLOR_YUYV) ||
173                 (_format == MM_UTIL_COLOR_RGBA) || (_format == MM_UTIL_COLOR_BGRX))
174                 _bool = FALSE;
175         else
176                 _bool = TRUE;
177
178         return _bool;
179 }
180
181 static gboolean __mm_select_rotate_plugin(mm_util_color_format_e _format)
182 {
183         mm_util_debug("_format: %d", _format);
184
185         if ((_format == MM_UTIL_COLOR_YUV420) || (_format == MM_UTIL_COLOR_I420) || (_format == MM_UTIL_COLOR_NV12)
186                 || (_format == MM_UTIL_COLOR_RGB24  || _format == MM_UTIL_COLOR_RGB16)) {
187                 return TRUE;
188         }
189
190         return FALSE;
191 }
192
193 static int __mm_util_get_crop_image_size(mm_util_color_format_e format, unsigned int width, unsigned int height, size_t *imgsize)
194 {
195         int ret = MM_UTIL_ERROR_NONE;
196         unsigned char x_chroma_shift = 0;
197         unsigned char y_chroma_shift = 0;
198         unsigned int w2, h2, stride, stride2;
199         size_t size, size2;
200
201         mm_util_fenter();
202
203         mm_util_retvm_if(imgsize == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid imgsize");
204         mm_util_retvm_if(__check_valid_picture_size(width, height) != MM_UTIL_ERROR_NONE, MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid width and height");
205
206         *imgsize = 0;
207
208         switch (format) {
209         case MM_UTIL_COLOR_I420:
210         case MM_UTIL_COLOR_YUV420:
211                 x_chroma_shift = 1;
212                 y_chroma_shift = 1;
213                 stride = MM_UTIL_ROUND_UP_4(width);
214                 h2 = ROUND_UP_X(height, x_chroma_shift);
215                 size = stride * h2;
216                 w2 = DIV_ROUND_UP_X(width, x_chroma_shift);
217                 stride2 = MM_UTIL_ROUND_UP_4(w2);
218                 h2 = DIV_ROUND_UP_X(height, y_chroma_shift);
219                 size2 = stride2 * h2;
220                 *imgsize = size + 2 * size2;
221                 break;
222         case MM_UTIL_COLOR_YUV422:
223         case MM_UTIL_COLOR_YUYV:
224         case MM_UTIL_COLOR_UYVY:
225         case MM_UTIL_COLOR_NV16:
226         case MM_UTIL_COLOR_NV61:
227                 stride = MM_UTIL_ROUND_UP_4(width) * 2;
228                 size = stride * height;
229                 *imgsize = size;
230                 break;
231
232         case MM_UTIL_COLOR_RGB16:
233                 stride = width * 2;
234                 size = stride * height;
235                 *imgsize = size;
236                 break;
237
238         case MM_UTIL_COLOR_RGB24:
239                 stride = width * 3;
240                 size = stride * height;
241                 *imgsize = size;
242                 break;
243
244         case MM_UTIL_COLOR_ARGB:
245         case MM_UTIL_COLOR_BGRA:
246         case MM_UTIL_COLOR_RGBA:
247         case MM_UTIL_COLOR_BGRX:
248                 stride = width * 4;
249                 size = stride * height;
250                 *imgsize = size;
251                 break;
252
253
254         case MM_UTIL_COLOR_NV12:
255         case MM_UTIL_COLOR_NV12_TILED:
256                 x_chroma_shift = 1;
257                 y_chroma_shift = 1;
258                 stride = MM_UTIL_ROUND_UP_4(width);
259                 h2 = ROUND_UP_X(height, y_chroma_shift);
260                 size = stride * h2;
261                 w2 = 2 * DIV_ROUND_UP_X(width, x_chroma_shift);
262                 stride2 = MM_UTIL_ROUND_UP_4(w2);
263                 h2 = DIV_ROUND_UP_X(height, y_chroma_shift);
264                 size2 = stride2 * h2;
265                 *imgsize = size + size2;
266                 break;
267
268         default:
269                 mm_util_error("Not supported format");
270                 return MM_UTIL_ERROR_NOT_SUPPORTED_FORMAT;
271         }
272
273         mm_util_debug("format: %d, *imgsize: %zu", format, *imgsize);
274
275         return ret;
276 }
277
278 static int __mm_set_imgp_info_s(imgp_info_s *_imgp_info_s, mm_util_color_format_e src_format, unsigned int src_width, unsigned int src_height, mm_util_color_format_e dst_format, unsigned int dst_width, unsigned int dst_height, mm_util_img_rotate_type angle)
279 {
280         int ret = MM_UTIL_ERROR_NONE;
281
282         mm_util_retvm_if(_imgp_info_s == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid _imgp_info_s");
283
284         _imgp_info_s->src_format = src_format;
285         _imgp_info_s->src_width = src_width;
286         _imgp_info_s->src_height = src_height;
287
288         _imgp_info_s->dst_format = dst_format;
289         _imgp_info_s->dst_width = dst_width;
290         _imgp_info_s->dst_height = dst_height;
291         _imgp_info_s->buffer_size = 0;
292         _imgp_info_s->angle = angle;
293
294         mm_util_debug("src_w[%u] src_h[%u] dst_w[%u] dst_h[%u] rotation[%d]", _imgp_info_s->src_width, _imgp_info_s->src_height, _imgp_info_s->dst_width, _imgp_info_s->dst_height, _imgp_info_s->angle);
295
296         return ret;
297 }
298
299 static GModule *__mm_util_imgp_initialize(imgp_plugin_type_e _imgp_plugin_type_e)
300 {
301         GModule *module = NULL;
302         mm_util_fenter();
303
304         if (_imgp_plugin_type_e == IMGP_NEON)
305                 module = g_module_open(PATH_NEON_LIB, G_MODULE_BIND_LAZY);
306         else if (_imgp_plugin_type_e == IMGP_GSTCS)
307                 module = g_module_open(PATH_GSTCS_LIB, G_MODULE_BIND_LAZY);
308
309         mm_util_retvm_if(module == NULL, NULL, "[%d] %s | %s module open failed", _imgp_plugin_type_e, PATH_NEON_LIB, PATH_GSTCS_LIB);
310         mm_util_debug("module: %p, g_module_name: %s", module, g_module_name(module));
311
312         return module;
313 }
314
315 static void __mm_util_imgp_finalize(GModule *module, imgp_info_s *_imgp_info_s)
316 {
317         if (module)
318                 g_module_close(module);
319
320         MMUTIL_SAFE_FREE(_imgp_info_s);
321
322         return;
323 }
324
325 static int __mm_util_crop_rgb32(const unsigned char *src, unsigned int src_width, unsigned int src_height,
326 unsigned int crop_start_x, unsigned int crop_start_y, unsigned int crop_dest_width, unsigned int crop_dest_height, unsigned char *dst)
327 {
328         int ret = MM_UTIL_ERROR_NONE;
329         unsigned int idx = 0;
330         int src_bytesperline = src_width * 4;
331         int dst_bytesperline = crop_dest_width * 4;
332
333         src += crop_start_y * src_bytesperline + 4 * crop_start_x;
334
335         for (idx = 0; idx < crop_dest_height; idx++) {
336                 memcpy(dst, src, dst_bytesperline);
337                 src += src_bytesperline;
338                 dst += dst_bytesperline;
339         }
340
341         return ret;
342 }
343
344 static int __mm_util_crop_rgb24(const unsigned char *src, unsigned int src_width, unsigned int src_height,
345 unsigned int crop_start_x, unsigned int crop_start_y, unsigned int crop_dest_width, unsigned int crop_dest_height, unsigned char *dst)
346 {
347         int ret = MM_UTIL_ERROR_NONE;
348         unsigned int idx = 0;
349         unsigned long src_bytesperline = src_width * 3;
350         unsigned long dst_bytesperline = crop_dest_width * 3;
351
352         src += crop_start_y * src_bytesperline + 3 * crop_start_x;
353
354         for (idx = 0; idx < crop_dest_height; idx++) {
355                 memcpy(dst, src, dst_bytesperline);
356                 src += src_bytesperline;
357                 dst += dst_bytesperline;
358         }
359
360         return ret;
361 }
362
363 static int __mm_util_crop_rgb16(const unsigned char *src, unsigned int src_width, unsigned int src_height,
364 unsigned int crop_start_x, unsigned int crop_start_y, unsigned int crop_dest_width, unsigned int crop_dest_height, unsigned char *dst)
365 {
366         int ret = MM_UTIL_ERROR_NONE;
367         unsigned int idx = 0;
368         unsigned long src_bytesperline = src_width * 2;
369         unsigned long dst_bytesperline = crop_dest_width * 2;
370
371         src += crop_start_y * src_bytesperline + 2 * crop_start_x;
372
373         for (idx = 0; idx < crop_dest_height; idx++) {
374                 memcpy(dst, src, dst_bytesperline);
375                 src += src_bytesperline;
376                 dst += dst_bytesperline;
377         }
378
379         return ret;
380 }
381
382 static int __mm_util_crop_yuv420(const unsigned char *src, unsigned int src_width, unsigned int src_height,
383 unsigned int crop_start_x, unsigned int crop_start_y, unsigned int crop_dest_width, unsigned int crop_dest_height, unsigned char *dst)
384 {
385         int ret = MM_UTIL_ERROR_NONE;
386         unsigned int idx = 0;
387         unsigned int start_x = crop_start_x;
388         unsigned int start_y = crop_start_y;
389
390         const unsigned char *_src = src + start_y * src_width + start_x;
391
392         /* Y */
393         for (idx = 0; idx < crop_dest_height; idx++) {
394                 memcpy(dst, _src, crop_dest_width);
395                 _src += src_width;
396                 dst += crop_dest_width;
397         }
398
399         /* U */
400         _src = src + src_height * src_width + (start_y / 2) * src_width / 2 + start_x / 2;
401         for (idx = 0; idx < crop_dest_height / 2; idx++) {
402                 memcpy(dst, _src, crop_dest_width / 2);
403                 _src += src_width / 2;
404                 dst += crop_dest_width / 2;
405         }
406
407         /* V */
408         _src = src + src_height * src_width * 5 / 4 + (start_y / 2) * src_width / 2 + start_x / 2;
409         for (idx = 0; idx < crop_dest_height / 2; idx++) {
410                 memcpy(dst, _src, crop_dest_width / 2);
411                 _src += src_width / 2;
412                 dst += crop_dest_width / 2;
413         }
414
415         return ret;
416 }
417
418 static IMGPInfoFunc __mm_util_initialize(imgp_type_e function, mm_util_color_format_e src_format, mm_util_color_format_e dst_format, GModule **module)
419 {
420         imgp_plugin_type_e _imgp_plugin_type_e = IMGP_GSTCS;
421         GModule *_module = NULL;
422         IMGPInfoFunc _func = NULL;
423
424         if (function == IMGP_CSC) {
425                 if (__mm_select_convert_plugin(src_format, dst_format))
426                         _imgp_plugin_type_e = IMGP_NEON;
427
428         } else if (function == IMGP_RSZ) {
429                 if (__mm_select_resize_plugin(src_format))
430                         _imgp_plugin_type_e = IMGP_NEON;
431
432         } else if (function == IMGP_ROT) {
433                 if (__mm_select_rotate_plugin(src_format))
434                         _imgp_plugin_type_e = IMGP_NEON;
435
436         } else {
437                 mm_util_error("invalid function : [%d]", function);
438         }
439
440         mm_util_debug("plugin type: %d", _imgp_plugin_type_e);
441
442         _module = __mm_util_imgp_initialize(_imgp_plugin_type_e);
443
444         if (_module == NULL) { /* when IMGP_NEON is NULL */
445                 _imgp_plugin_type_e = IMGP_GSTCS;
446                 mm_util_debug("You use %s module", PATH_GSTCS_LIB);
447                 _module = __mm_util_imgp_initialize(_imgp_plugin_type_e);
448         }
449
450         mm_util_debug("mm_util_imgp_func: %p", _module);
451
452         if (_module == NULL) {
453                 mm_util_error("invalid module");
454                 return NULL;
455         }
456
457         g_module_symbol(_module, IMGP_FUNC_NAME, (gpointer *)&_func);
458
459         if (_func == NULL) {
460                 mm_util_error("invalid function");
461                 g_module_close(_module);
462                 return NULL;
463         }
464
465         *module = _module;
466
467         return _func;
468 }
469
470 static bool __mm_util_check_format(mm_util_color_format_e color_format)
471 {
472         if ((color_format >= MM_UTIL_COLOR_YUV420) && (color_format <= MM_UTIL_COLOR_BGRX))
473                 return TRUE;
474
475         return FALSE;
476 }
477
478 int mm_util_convert_colorspace(mm_util_image_h src, mm_util_color_format_e color, mm_util_image_h *dst)
479 {
480         int ret = MM_UTIL_ERROR_NONE;
481         IMGPInfoFunc _mm_util_imgp_func = NULL;
482         GModule *_module = NULL;
483         unsigned char *output_buffer = NULL;
484         mm_image_info_s *_src = (mm_image_info_s *)src;
485         mm_util_image_h _convert_image = NULL;
486
487         mm_util_fenter();
488
489         mm_util_retvm_if(!IS_VALID_IMAGE(src), MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid src");
490         mm_util_retvm_if(!__mm_util_check_format(color), MM_UTIL_ERROR_NOT_SUPPORTED_FORMAT, "Not supported format [%d]", color);
491         mm_util_retvm_if(!dst, MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid dst");
492
493         mm_util_debug("[Input] format[%d]", color);
494         mm_image_debug_image(src, "Input");
495
496         _mm_util_imgp_func = __mm_util_initialize(IMGP_CSC, _src->color, color, &_module);
497         if (_mm_util_imgp_func == NULL) {
498                 mm_util_error("ERROR - __mm_util_initialize");
499                 return MM_UTIL_ERROR_INVALID_OPERATION;
500         }
501
502         imgp_info_s *_imgp_info_s = (imgp_info_s *) calloc(1, sizeof(imgp_info_s));
503         if (_imgp_info_s == NULL) {
504                 mm_util_error("ERROR - alloc handle");
505                 ret = MM_UTIL_ERROR_OUT_OF_MEMORY;
506                 goto ERROR;
507         }
508
509         ret = __mm_set_imgp_info_s(_imgp_info_s, _src->color, _src->width, _src->height, color, _src->width, _src->height, MM_UTIL_ROTATE_0);
510         if (ret != MM_UTIL_ERROR_NONE) {
511                 mm_util_error("__mm_set_imgp_info_s failed");
512                 ret = MM_UTIL_ERROR_INVALID_OPERATION;
513                 goto ERROR;
514         }
515
516         ret = _mm_util_imgp_func(_imgp_info_s, _src->data, &output_buffer, IMGP_CSC);
517         if (ret != MM_UTIL_ERROR_NONE) {
518                 mm_util_error("image processing failed");
519                 goto ERROR;
520         }
521
522         if ((_imgp_info_s->dst_width != _imgp_info_s->output_stride || _imgp_info_s->dst_height != _imgp_info_s->output_elevation)) {
523                 ret = mm_image_create_image(_imgp_info_s->output_stride, _imgp_info_s->output_elevation, color, output_buffer, _imgp_info_s->buffer_size, &_convert_image);
524                 if (ret != MM_UTIL_ERROR_NONE) {
525                         mm_util_error("mm_image_create_image failed");
526                         ret = MM_UTIL_ERROR_INVALID_OPERATION;
527                         goto ERROR;
528                 }
529
530                 ret = mm_util_crop_image(_convert_image, 0, 0, _imgp_info_s->dst_width, _imgp_info_s->dst_height, dst);
531                 mm_image_destroy_image(_convert_image);
532                 if (ret != MM_UTIL_ERROR_NONE) {
533                         mm_util_error("mm_util_crop_image failed");
534                         ret = MM_UTIL_ERROR_INVALID_OPERATION;
535                         goto ERROR;
536                 }
537         } else {
538                 ret = mm_image_create_image(_src->width, _src->height, color, output_buffer, _imgp_info_s->buffer_size, dst);
539                 if (ret != MM_UTIL_ERROR_NONE) {
540                         mm_util_error("mm_image_create_image failed");
541                         ret = MM_UTIL_ERROR_INVALID_OPERATION;
542                         goto ERROR;
543                 }
544         }
545
546 ERROR:
547         /* Finalize */
548         __mm_util_imgp_finalize(_module, _imgp_info_s);
549         MMUTIL_SAFE_FREE(output_buffer);
550
551         mm_util_fleave();
552
553         return ret;
554 }
555
556 int mm_util_resize_image(mm_util_image_h src, unsigned int width, unsigned int height, mm_util_image_h *dst)
557 {
558         int ret = MM_UTIL_ERROR_NONE;
559         IMGPInfoFunc _mm_util_imgp_func = NULL;
560         GModule *_module = NULL;
561         unsigned char *output_buffer = NULL;
562         mm_image_info_s *_src = (mm_image_info_s *)src;
563         mm_util_image_h _resize_image = NULL;
564
565         mm_util_fenter();
566
567         mm_util_retvm_if(!IS_VALID_IMAGE(src), MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid src");
568         mm_util_retvm_if(width == 0, MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid width");
569         mm_util_retvm_if(height == 0, MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid height");
570         mm_util_retvm_if(!dst, MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid dst");
571
572         mm_util_debug("[Input] width[%u] height[%u]", width, height);
573         mm_image_debug_image(src, "Input");
574
575         _mm_util_imgp_func = __mm_util_initialize(IMGP_RSZ, _src->color, 0, &_module);
576         mm_util_retvm_if(_mm_util_imgp_func == NULL, MM_UTIL_ERROR_INVALID_OPERATION, "fail __mm_util_initialize");
577
578         imgp_info_s *_imgp_info_s = (imgp_info_s *) calloc(1, sizeof(imgp_info_s));
579         if (_imgp_info_s == NULL) {
580                 mm_util_error("ERROR - alloc handle");
581                 ret = MM_UTIL_ERROR_OUT_OF_MEMORY;
582                 goto ERROR;
583         }
584
585         ret = __mm_set_imgp_info_s(_imgp_info_s, _src->color, _src->width, _src->height, _src->color, width, height, MM_UTIL_ROTATE_0);
586         if (ret != MM_UTIL_ERROR_NONE) {
587                 mm_util_error("__mm_set_imgp_info_s failed [%d]", ret);
588                 ret = MM_UTIL_ERROR_INVALID_OPERATION;
589                 goto ERROR;
590         }
591
592         if (g_strrstr(g_module_name(_module), GST)) {
593                 if (__mm_gst_can_resize_format(_imgp_info_s->src_format) == FALSE) {
594                         mm_util_error("#RESIZE ERROR# IMAGE_NOT_SUPPORT_FORMAT");
595                         ret = MM_UTIL_ERROR_NOT_SUPPORTED_FORMAT;
596                         goto ERROR;
597                 }
598         }
599
600         ret = _mm_util_imgp_func(_imgp_info_s, _src->data, &output_buffer, IMGP_RSZ);
601         mm_util_debug("_mm_util_imgp_func, ret: %d", ret);
602         if (ret != MM_UTIL_ERROR_NONE) {
603                 mm_util_error("image processing failed");
604                 goto ERROR;
605         }
606
607         if ((_imgp_info_s->dst_width != _imgp_info_s->output_stride || _imgp_info_s->dst_height != _imgp_info_s->output_elevation)) {
608                 ret = mm_image_create_image(_imgp_info_s->output_stride, _imgp_info_s->output_elevation, _src->color, output_buffer, _imgp_info_s->buffer_size, &_resize_image);
609                 if (ret != MM_UTIL_ERROR_NONE) {
610                         mm_util_error("mm_image_create_image failed");
611                         ret = MM_UTIL_ERROR_INVALID_OPERATION;
612                         goto ERROR;
613                 }
614
615                 ret = mm_util_crop_image(_resize_image, 0, 0, _imgp_info_s->dst_width, _imgp_info_s->dst_height, dst);
616                 mm_image_destroy_image(_resize_image);
617                 if (ret != MM_UTIL_ERROR_NONE) {
618                         mm_util_error("mm_util_crop_image failed");
619                         ret = MM_UTIL_ERROR_INVALID_OPERATION;
620                         goto ERROR;
621                 }
622         } else {
623                 ret = mm_image_create_image(width, height, _src->color, output_buffer, _imgp_info_s->buffer_size, dst);
624                 if (ret != MM_UTIL_ERROR_NONE) {
625                         mm_util_error("mm_image_create_image failed");
626                         ret = MM_UTIL_ERROR_INVALID_OPERATION;
627                         goto ERROR;
628                 }
629         }
630
631 ERROR:
632         /* Finalize */
633         __mm_util_imgp_finalize(_module, _imgp_info_s);
634         MMUTIL_SAFE_FREE(output_buffer);
635
636         mm_util_fleave();
637
638         return ret;
639 }
640
641 int mm_util_rotate_image(mm_util_image_h src, mm_util_img_rotate_type angle, mm_util_image_h *dst)
642 {
643         int ret = MM_UTIL_ERROR_NONE;
644         IMGPInfoFunc _mm_util_imgp_func = NULL;
645         GModule *_module = NULL;
646         unsigned char *output_buffer = NULL;
647         unsigned int uint_w = 0;
648         unsigned int uint_h = 0;
649         mm_image_info_s *_src = (mm_image_info_s *)src;
650         mm_util_image_h _rotate_image = NULL;
651
652         mm_util_fenter();
653
654         mm_util_retvm_if(!IS_VALID_IMAGE(src), MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid src");
655         mm_util_retvm_if((angle < MM_UTIL_ROTATE_0) || (angle >= MM_UTIL_ROTATE_NUM), MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid angle [%d]", angle);
656         mm_util_retvm_if(!dst, MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid dst");
657
658         mm_util_debug("[Input] angle[%d]", angle);
659         mm_image_debug_image(src, "Input");
660
661         _mm_util_imgp_func = __mm_util_initialize(IMGP_ROT, _src->color, 0, &_module);
662         if (_mm_util_imgp_func == NULL) {
663                 mm_util_error("ERROR - __mm_util_initialize");
664                 return MM_UTIL_ERROR_INVALID_OPERATION;
665         }
666
667         imgp_info_s *_imgp_info_s = (imgp_info_s *) calloc(1, sizeof(imgp_info_s));
668         if (_imgp_info_s == NULL) {
669                 mm_util_error("ERROR - alloc handle");
670                 ret = MM_UTIL_ERROR_OUT_OF_MEMORY;
671                 goto ERROR;
672         }
673
674         if ((angle == MM_UTIL_ROTATE_90) || (angle == MM_UTIL_ROTATE_270)) {
675                 uint_w = _src->height;
676                 uint_h = _src->width;
677         } else {
678                 uint_w = _src->width;
679                 uint_h = _src->height;
680         }
681
682         ret = __mm_set_imgp_info_s(_imgp_info_s, _src->color, _src->width, _src->height, _src->color, uint_w, uint_h, angle);
683         mm_util_debug("__mm_set_imgp_info_s");
684         if (ret != MM_UTIL_ERROR_NONE) {
685                 mm_util_error("__mm_set_imgp_info_s failed");
686                 ret = MM_UTIL_ERROR_INVALID_OPERATION;
687                 goto ERROR;
688         }
689
690         if (g_strrstr(g_module_name(_module), GST)) {
691                 if (__mm_gst_can_rotate_format(_imgp_info_s->src_format) == FALSE) {
692                         mm_util_error("#gstreamer ROTATE ERROR# IMAGE_NOT_SUPPORT_FORMAT");
693                         ret = MM_UTIL_ERROR_NOT_SUPPORTED_FORMAT;
694                         goto ERROR;
695                 }
696         }
697
698         ret = _mm_util_imgp_func(_imgp_info_s, _src->data, &output_buffer, IMGP_ROT);
699         if (ret != MM_UTIL_ERROR_NONE) {
700                 mm_util_error("image processing failed");
701                 goto ERROR;
702         }
703
704         if ((_imgp_info_s->dst_width != _imgp_info_s->output_stride || _imgp_info_s->dst_height != _imgp_info_s->output_elevation)) {
705                 unsigned int start_x = 0;
706                 unsigned int start_y = 0;
707                 if (angle == MM_UTIL_ROTATE_90) {
708                         start_x = 0;
709                         start_y = 0;
710                 } else if (angle == MM_UTIL_ROTATE_180) {
711                         start_x = _imgp_info_s->output_stride-_imgp_info_s->dst_width;
712                         start_y = 0;
713                 } else if (angle == MM_UTIL_ROTATE_270) {
714                         start_x = 0;
715                         start_y = _imgp_info_s->output_elevation - _imgp_info_s->dst_height;
716                 }
717                 ret = mm_image_create_image(_imgp_info_s->output_stride, _imgp_info_s->output_elevation, _src->color, output_buffer, _imgp_info_s->buffer_size, &_rotate_image);
718                 if (ret != MM_UTIL_ERROR_NONE) {
719                         mm_util_error("mm_image_create_image failed");
720                         ret = MM_UTIL_ERROR_INVALID_OPERATION;
721                         goto ERROR;
722                 }
723
724                 ret = mm_util_crop_image(_rotate_image, 0, 0, start_x, start_y, dst);
725                 mm_image_destroy_image(_rotate_image);
726                 if (ret != MM_UTIL_ERROR_NONE) {
727                         mm_util_error("mm_util_crop_image failed");
728                         ret = MM_UTIL_ERROR_INVALID_OPERATION;
729                         goto ERROR;
730                 }
731         } else {
732                 ret = mm_image_create_image(uint_w, uint_h, _src->color, output_buffer, _imgp_info_s->buffer_size, dst);
733                 if (ret != MM_UTIL_ERROR_NONE) {
734                         mm_util_error("mm_image_create_image failed");
735                         ret = MM_UTIL_ERROR_INVALID_OPERATION;
736                         goto ERROR;
737                 }
738         }
739
740 ERROR:
741         /* Finalize */
742         __mm_util_imgp_finalize(_module, _imgp_info_s);
743         MMUTIL_SAFE_FREE(output_buffer);
744
745         mm_util_fleave();
746
747         return ret;
748 }
749
750 int mm_util_crop_image(mm_util_image_h src, unsigned int start_x, unsigned int start_y, unsigned int width, unsigned int height, mm_util_image_h *dst)
751 {
752         int ret = MM_UTIL_ERROR_NONE;
753         mm_image_info_s *_src = (mm_image_info_s *)src;
754         unsigned int _width = width;
755         unsigned int _height = height;
756         unsigned char *_buffer = NULL;
757         size_t _buffer_size = 0;
758
759         mm_util_fenter();
760
761         mm_util_retvm_if(!IS_VALID_IMAGE(src), MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid src");
762         mm_util_retvm_if((start_x + width > _src->width), MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid position [%u][%u]", start_x, width);
763         mm_util_retvm_if((start_y + height > _src->height), MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid position [%u][%u]", start_y, height);
764         mm_util_retvm_if(!dst, MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid dst");
765
766         mm_util_debug("[Input] start_x[%u] start_y[%u] width[%u] height[%u]", start_x, start_y, width, height);
767         mm_image_debug_image(src, "Input");
768
769         if (_src->color == MM_UTIL_COLOR_I420 || _src->color == MM_UTIL_COLOR_YUV420) {
770                 if ((_width % 2) != 0) {
771                         mm_util_warn("#YUV Width value(%u) must be even at least# ", _width);
772                         _width = ((_width+1)>>1)<<1;
773                         mm_util_debug("Image isplay is suceeded when YUV crop width value %u", _width);
774                 }
775
776                 if ((_height % 2) != 0) { /* height value must be also even when crop yuv image */
777                         mm_util_warn("#YUV Height value(%u) must be even at least# ", _height);
778                         _height = ((_height+1)>>1)<<1;
779                         mm_util_debug("Image isplay is suceeded when YUV crop height value %u", _height);
780                 }
781         }
782
783         __mm_util_get_crop_image_size(_src->color, _width, _height, &_buffer_size);
784         mm_util_retvm_if(!_buffer_size, MM_UTIL_ERROR_INVALID_OPERATION, "fail to get dst_buf_size");
785
786         _buffer = calloc(1, _buffer_size);
787         mm_util_retvm_if(!_buffer, MM_UTIL_ERROR_OUT_OF_MEMORY, "Memory allocation failed");
788
789         switch (_src->color) {
790         case MM_UTIL_COLOR_RGB16: {
791                 ret = __mm_util_crop_rgb16(_src->data, _src->width, _src->height, start_x, start_y, _width, _height, _buffer);
792                 break;
793                 }
794         case MM_UTIL_COLOR_RGB24: {
795                 ret = __mm_util_crop_rgb24(_src->data, _src->width, _src->height, start_x, start_y, _width, _height, _buffer);
796                 break;
797                 }
798         case MM_UTIL_COLOR_ARGB:
799         case MM_UTIL_COLOR_BGRA:
800         case MM_UTIL_COLOR_RGBA:
801         case MM_UTIL_COLOR_BGRX: {
802                 ret = __mm_util_crop_rgb32(_src->data, _src->width, _src->height, start_x, start_y, _width, _height, _buffer);
803                 break;
804                 }
805         case MM_UTIL_COLOR_I420:
806         case MM_UTIL_COLOR_YUV420: {
807                 ret = __mm_util_crop_yuv420(_src->data, _src->width, _src->height, start_x, start_y, _width, _height, _buffer);
808                 break;
809                 }
810         default:
811                 mm_util_debug("Not supported format");
812                 MMUTIL_SAFE_FREE(_buffer);
813                 return MM_UTIL_ERROR_NOT_SUPPORTED_FORMAT;
814         }
815
816         ret = mm_image_create_image(_width, _height, _src->color, _buffer, _buffer_size, dst);
817
818         MMUTIL_SAFE_FREE(_buffer);
819         mm_util_fleave();
820
821         return ret;
822 }
823
824 int mm_util_get_image_size(mm_util_color_format_e format, unsigned int width, unsigned int height, size_t *imgsize)
825 {
826         int ret = MM_UTIL_ERROR_NONE;
827         unsigned char x_chroma_shift = 0;
828         unsigned char y_chroma_shift = 0;
829         unsigned int w2, h2, stride, stride2;
830         size_t size, size2;
831
832         mm_util_fenter();
833
834         mm_util_retvm_if((imgsize == NULL), MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid imgsize");
835         mm_util_retvm_if((IS_VALID_COLOR(format) == FALSE), MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid format [%d]", format);
836         mm_util_retvm_if((__check_valid_picture_size(width, height) != MM_UTIL_ERROR_NONE), MM_UTIL_ERROR_INVALID_PARAMETER, "image width & height is too big");
837
838         *imgsize = 0;
839
840         switch (format) {
841         case MM_UTIL_COLOR_I420:
842         case MM_UTIL_COLOR_YUV420:
843                 x_chroma_shift = 1;
844                 y_chroma_shift = 1;
845                 stride = MM_UTIL_ROUND_UP_4(width);
846                 h2 = ROUND_UP_X(height, x_chroma_shift);
847                 size = stride * h2;
848                 w2 = DIV_ROUND_UP_X(width, x_chroma_shift);
849                 stride2 = MM_UTIL_ROUND_UP_4(w2);
850                 h2 = DIV_ROUND_UP_X(height, y_chroma_shift);
851                 size2 = stride2 * h2;
852                 *imgsize = size + 2 * size2;
853                 break;
854         case MM_UTIL_COLOR_YUV422:
855         case MM_UTIL_COLOR_YUYV:
856         case MM_UTIL_COLOR_UYVY:
857         case MM_UTIL_COLOR_NV16:
858         case MM_UTIL_COLOR_NV61:
859                 stride = MM_UTIL_ROUND_UP_4(width) * 2;
860                 size = stride * height;
861                 *imgsize = size;
862                 break;
863
864         case MM_UTIL_COLOR_RGB16:
865                 stride = MM_UTIL_ROUND_UP_4(width) * 2;
866                 size = stride * height;
867                 *imgsize = size;
868                 break;
869
870         case MM_UTIL_COLOR_RGB24:
871                 stride = MM_UTIL_ROUND_UP_4(width) * 3;
872                 size = stride * height;
873                 *imgsize = size;
874                 break;
875
876         case MM_UTIL_COLOR_ARGB:
877         case MM_UTIL_COLOR_BGRA:
878         case MM_UTIL_COLOR_RGBA:
879         case MM_UTIL_COLOR_BGRX:
880                 stride = width * 4;
881                 size = stride * height;
882                 *imgsize = size;
883                 break;
884
885         case MM_UTIL_COLOR_NV12:
886         case MM_UTIL_COLOR_NV12_TILED:
887         case MM_UTIL_COLOR_NV21:
888                 x_chroma_shift = 1;
889                 y_chroma_shift = 1;
890                 stride = MM_UTIL_ROUND_UP_4(width);
891                 h2 = ROUND_UP_X(height, y_chroma_shift);
892                 size = stride * h2;
893                 w2 = 2 * DIV_ROUND_UP_X(width, x_chroma_shift);
894                 stride2 = MM_UTIL_ROUND_UP_4(w2);
895                 h2 = DIV_ROUND_UP_X(height, y_chroma_shift);
896                 size2 = stride2 * h2;
897                 *imgsize = size + size2;
898                 break;
899
900         default:
901                 mm_util_error("Not supported format");
902                 return MM_UTIL_ERROR_NOT_SUPPORTED_FORMAT;
903         }
904
905         mm_util_debug("format: %u, *imgsize: %zu", format, *imgsize);
906
907         return ret;
908 }
909