Modify mm_util_resize_image() API to receive allocated buffer and buffer info
[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 #include "mm_util_common.h"
28
29 #define MM_UTIL_ROUND_UP_2(num) (((num)+1)&~1)
30 #define MM_UTIL_ROUND_UP_4(num) (((num)+3)&~3)
31 #define MM_UTIL_ROUND_UP_8(num) (((num)+7)&~7)
32 #define MM_UTIL_ROUND_UP_16(num) (((num)+15)&~15)
33 #define GEN_MASK(x) ((1<<(x))-1)
34 #define ROUND_UP_X(v, x) (((v) + GEN_MASK(x)) & ~GEN_MASK(x))
35 #define DIV_ROUND_UP_X(v, x) (((v) + GEN_MASK(x)) >> (x))
36 #define GST "gstcs"
37
38 typedef gboolean(*IMGPInfoFunc) (imgp_info_s *, const unsigned char *, unsigned char **, imgp_plugin_type_e);
39 static int __mm_util_transform_exec(mm_util_s *handle, color_image_data_s *source_image);
40
41 static int check_valid_picture_size(int width, int height)
42 {
43         if ((int)width > 0 && (int)height > 0 &&
44                 ((width + 128) * (unsigned long long)(height + 128)) < INT_MAX/4)
45                 return MM_UTIL_ERROR_NONE;
46
47         return MM_UTIL_ERROR_INVALID_PARAMETER;
48 }
49
50 static void __mm_destroy_temp_buffer(unsigned char *buffer[])
51 {
52         int i = 0;
53
54         for (i = 0; i < 4; i++)
55                 MMUTIL_SAFE_FREE(buffer[i]);
56 }
57
58 static gboolean __mm_gst_can_resize_format(mm_util_color_format_e color_format)
59 {
60         gboolean _bool = FALSE;
61
62         mm_util_debug("color_format [%d]", color_format);
63
64         switch (color_format) {
65         case MM_UTIL_COLOR_YUV420:
66         case MM_UTIL_COLOR_YUV422:
67         case MM_UTIL_COLOR_I420:
68         case MM_UTIL_COLOR_UYVY:
69         case MM_UTIL_COLOR_YUYV:
70         case MM_UTIL_COLOR_RGB16:
71         case MM_UTIL_COLOR_RGB24:
72         case MM_UTIL_COLOR_ARGB:
73         case MM_UTIL_COLOR_BGRA:
74         case MM_UTIL_COLOR_RGBA:
75         case MM_UTIL_COLOR_BGRX:
76                 _bool = TRUE;
77                 break;
78         default:
79                 mm_util_error("Not supported format");  //only not support NV12
80         }
81
82         return _bool;
83 }
84
85 static gboolean __mm_gst_can_rotate_format(mm_util_color_format_e color_format)
86 {
87         gboolean _bool = FALSE;
88
89         mm_util_debug("color_format [%d]", color_format);
90
91         switch (color_format) {
92         case MM_UTIL_COLOR_YUV420:
93         case MM_UTIL_COLOR_I420:
94         case MM_UTIL_COLOR_RGB24:
95         case MM_UTIL_COLOR_ARGB:
96         case MM_UTIL_COLOR_BGRA:
97         case MM_UTIL_COLOR_RGBA:
98                 _bool = TRUE;
99                 break;
100         default:
101                 mm_util_error("Not supported format");
102         }
103
104         return _bool;
105 }
106
107 static gboolean __mm_select_convert_plugin(mm_util_color_format_e src_format, mm_util_color_format_e dst_format)
108 {
109         gboolean _bool = FALSE;
110
111         mm_util_debug("src_format: %d, dst_format:%d", src_format, dst_format);
112
113         if (((src_format == MM_UTIL_COLOR_YUV420) && (dst_format == MM_UTIL_COLOR_NV12)) ||
114                 ((src_format == MM_UTIL_COLOR_YUV420) && (dst_format == MM_UTIL_COLOR_RGB16)) ||
115                 ((src_format == MM_UTIL_COLOR_YUV420) && (dst_format == MM_UTIL_COLOR_RGB24)) ||
116                 ((src_format == MM_UTIL_COLOR_YUV420) && (dst_format == MM_UTIL_COLOR_ARGB)) ||
117                 ((src_format == MM_UTIL_COLOR_YUV420) && (dst_format == MM_UTIL_COLOR_BGRA)) ||
118                 ((src_format == MM_UTIL_COLOR_YUV420) && (dst_format == MM_UTIL_COLOR_RGBA)) ||
119                 ((src_format == MM_UTIL_COLOR_YUV420) && (dst_format == MM_UTIL_COLOR_NV12_TILED)) ||
120
121                 ((src_format == MM_UTIL_COLOR_I420) && (dst_format == MM_UTIL_COLOR_NV12)) ||
122                 ((src_format == MM_UTIL_COLOR_I420) && (dst_format == MM_UTIL_COLOR_RGB16)) ||
123                 ((src_format == MM_UTIL_COLOR_I420) && (dst_format == MM_UTIL_COLOR_RGB24)) ||
124                 ((src_format == MM_UTIL_COLOR_I420) && (dst_format == MM_UTIL_COLOR_ARGB)) ||
125                 ((src_format == MM_UTIL_COLOR_I420) && (dst_format == MM_UTIL_COLOR_BGRA)) ||
126                 ((src_format == MM_UTIL_COLOR_I420) && (dst_format == MM_UTIL_COLOR_RGBA)) ||
127                 ((src_format == MM_UTIL_COLOR_I420) && (dst_format == MM_UTIL_COLOR_NV12_TILED)) ||
128
129                 ((src_format == MM_UTIL_COLOR_NV12) && (dst_format == MM_UTIL_COLOR_YUV420)) ||
130                 ((src_format == MM_UTIL_COLOR_NV12) && (dst_format == MM_UTIL_COLOR_I420)) ||
131                 ((src_format == MM_UTIL_COLOR_NV12) && (dst_format == MM_UTIL_COLOR_RGB16)) ||
132                 ((src_format == MM_UTIL_COLOR_NV12) && (dst_format == MM_UTIL_COLOR_RGB24)) ||
133                 ((src_format == MM_UTIL_COLOR_NV12) && (dst_format == MM_UTIL_COLOR_ARGB)) ||
134                 ((src_format == MM_UTIL_COLOR_NV12) && (dst_format == MM_UTIL_COLOR_BGRA)) ||
135                 ((src_format == MM_UTIL_COLOR_NV12) && (dst_format == MM_UTIL_COLOR_RGBA)) ||
136
137                 ((src_format == MM_UTIL_COLOR_UYVY) && (dst_format == MM_UTIL_COLOR_RGB16)) ||
138                 ((src_format == MM_UTIL_COLOR_UYVY) && (dst_format == MM_UTIL_COLOR_RGB24)) ||
139
140                 ((src_format == MM_UTIL_COLOR_YUYV) && (dst_format == MM_UTIL_COLOR_RGB16)) ||
141                 ((src_format == MM_UTIL_COLOR_YUYV) && (dst_format == MM_UTIL_COLOR_RGB24)) ||
142                 ((src_format == MM_UTIL_COLOR_YUYV) && (dst_format == MM_UTIL_COLOR_ARGB)) ||
143                 ((src_format == MM_UTIL_COLOR_YUYV) && (dst_format == MM_UTIL_COLOR_BGRA)) ||
144                 ((src_format == MM_UTIL_COLOR_YUYV) && (dst_format == MM_UTIL_COLOR_RGBA)) ||
145
146                 ((src_format == MM_UTIL_COLOR_RGB16) && (dst_format == MM_UTIL_COLOR_YUV420)) ||
147                 ((src_format == MM_UTIL_COLOR_RGB16) && (dst_format == MM_UTIL_COLOR_I420)) ||
148                 ((src_format == MM_UTIL_COLOR_RGB16) && (dst_format == MM_UTIL_COLOR_NV12)) ||
149
150                 ((src_format == MM_UTIL_COLOR_RGB24) && (dst_format == MM_UTIL_COLOR_YUV420)) ||
151                 ((src_format == MM_UTIL_COLOR_RGB24) && (dst_format == MM_UTIL_COLOR_I420)) ||
152                 ((src_format == MM_UTIL_COLOR_RGB24) && (dst_format == MM_UTIL_COLOR_NV12)) ||
153
154                 ((src_format == MM_UTIL_COLOR_ARGB) && (dst_format == MM_UTIL_COLOR_YUV420)) ||
155                 ((src_format == MM_UTIL_COLOR_ARGB) && (dst_format == MM_UTIL_COLOR_I420)) ||
156                 ((src_format == MM_UTIL_COLOR_ARGB) && (dst_format == MM_UTIL_COLOR_NV12)) ||
157
158                 ((src_format == MM_UTIL_COLOR_BGRA) && (dst_format == MM_UTIL_COLOR_YUV420)) ||
159                 ((src_format == MM_UTIL_COLOR_BGRA) && (dst_format == MM_UTIL_COLOR_I420)) ||
160                 ((src_format == MM_UTIL_COLOR_BGRA) && (dst_format == MM_UTIL_COLOR_NV12)) ||
161                 ((src_format == MM_UTIL_COLOR_RGBA) && (dst_format == MM_UTIL_COLOR_YUV420)) ||
162                 ((src_format == MM_UTIL_COLOR_RGBA) && (dst_format == MM_UTIL_COLOR_I420)) ||
163                 ((src_format == MM_UTIL_COLOR_RGBA) && (dst_format == MM_UTIL_COLOR_NV12)) ||
164                 ((src_format == MM_UTIL_COLOR_RGBA) && (dst_format == MM_UTIL_COLOR_RGB16)) ||
165
166                 ((src_format == MM_UTIL_COLOR_NV12_TILED) && (dst_format == MM_UTIL_COLOR_YUV420)) ||
167                 ((src_format == MM_UTIL_COLOR_NV12_TILED) && (dst_format == MM_UTIL_COLOR_I420)) ||
168                 ((src_format == MM_UTIL_COLOR_NV12_TILED) && (dst_format == MM_UTIL_COLOR_NV12)) ||
169                 ((src_format == MM_UTIL_COLOR_NV12_TILED) && (dst_format == MM_UTIL_COLOR_RGB16)) ||
170                 ((src_format == MM_UTIL_COLOR_NV12_TILED) && (dst_format == MM_UTIL_COLOR_RGB24)) ||
171                 ((src_format == MM_UTIL_COLOR_NV12_TILED) && (dst_format == MM_UTIL_COLOR_ARGB)) ||
172                 ((src_format == MM_UTIL_COLOR_NV12_TILED) && (dst_format == MM_UTIL_COLOR_BGRA)) ||
173                 ((src_format == MM_UTIL_COLOR_NV12_TILED) && (dst_format == MM_UTIL_COLOR_RGBA))) {
174
175                 _bool = TRUE;
176         }
177
178         return _bool;
179 }
180
181 static gboolean __mm_select_resize_plugin(mm_util_color_format_e _format)
182 {
183         gboolean _bool = FALSE;
184
185         mm_util_debug("_format: %d", _format);
186
187         if ((_format == MM_UTIL_COLOR_UYVY) || (_format == MM_UTIL_COLOR_YUYV) ||
188                 (_format == MM_UTIL_COLOR_RGBA) || (_format == MM_UTIL_COLOR_BGRX))
189                 _bool = FALSE;
190         else
191                 _bool = TRUE;
192
193         return _bool;
194 }
195
196 static gboolean __mm_select_rotate_plugin(mm_util_color_format_e _format)
197 {
198         mm_util_debug("_format: %d", _format);
199
200         if ((_format == MM_UTIL_COLOR_YUV420) || (_format == MM_UTIL_COLOR_I420) || (_format == MM_UTIL_COLOR_NV12)
201                 || (_format == MM_UTIL_COLOR_RGB24  || _format == MM_UTIL_COLOR_RGB16)) {
202                 return TRUE;
203         }
204
205         return FALSE;
206 }
207
208 static int __mm_util_get_crop_image_size(mm_util_color_format_e format, unsigned int width, unsigned int height, unsigned int *imgsize)
209 {
210         int ret = MM_UTIL_ERROR_NONE;
211         unsigned char x_chroma_shift = 0;
212         unsigned char y_chroma_shift = 0;
213         int size, w2, h2, size2;
214         int stride, stride2;
215
216         mm_util_fenter();
217
218         mm_util_retvm_if(imgsize == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid imgsize");
219         mm_util_retvm_if(check_valid_picture_size(width, height) != MM_UTIL_ERROR_NONE, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid width and height");
220
221         *imgsize = 0;
222
223         switch (format) {
224         case MM_UTIL_COLOR_I420:
225         case MM_UTIL_COLOR_YUV420:
226                 x_chroma_shift = 1;
227                 y_chroma_shift = 1;
228                 stride = MM_UTIL_ROUND_UP_4(width);
229                 h2 = ROUND_UP_X(height, x_chroma_shift);
230                 size = stride * h2;
231                 w2 = DIV_ROUND_UP_X(width, x_chroma_shift);
232                 stride2 = MM_UTIL_ROUND_UP_4(w2);
233                 h2 = DIV_ROUND_UP_X(height, y_chroma_shift);
234                 size2 = stride2 * h2;
235                 *imgsize = size + 2 * size2;
236                 break;
237         case MM_UTIL_COLOR_YUV422:
238         case MM_UTIL_COLOR_YUYV:
239         case MM_UTIL_COLOR_UYVY:
240         case MM_UTIL_COLOR_NV16:
241         case MM_UTIL_COLOR_NV61:
242                 stride = MM_UTIL_ROUND_UP_4(width) * 2;
243                 size = stride * height;
244                 *imgsize = size;
245                 break;
246
247         case MM_UTIL_COLOR_RGB16:
248                 stride = width * 2;
249                 size = stride * height;
250                 *imgsize = size;
251                 break;
252
253         case MM_UTIL_COLOR_RGB24:
254                 stride = width * 3;
255                 size = stride * height;
256                 *imgsize = size;
257                 break;
258
259         case MM_UTIL_COLOR_ARGB:
260         case MM_UTIL_COLOR_BGRA:
261         case MM_UTIL_COLOR_RGBA:
262         case MM_UTIL_COLOR_BGRX:
263                 stride = width * 4;
264                 size = stride * height;
265                 *imgsize = size;
266                 break;
267
268
269         case MM_UTIL_COLOR_NV12:
270         case MM_UTIL_COLOR_NV12_TILED:
271                 x_chroma_shift = 1;
272                 y_chroma_shift = 1;
273                 stride = MM_UTIL_ROUND_UP_4(width);
274                 h2 = ROUND_UP_X(height, y_chroma_shift);
275                 size = stride * h2;
276                 w2 = 2 * DIV_ROUND_UP_X(width, x_chroma_shift);
277                 stride2 = MM_UTIL_ROUND_UP_4(w2);
278                 h2 = DIV_ROUND_UP_X(height, y_chroma_shift);
279                 size2 = stride2 * h2;
280                 *imgsize = size + size2;
281                 break;
282
283         default:
284                 mm_util_error("Not supported format");
285                 return MM_UTIL_ERROR_NOT_SUPPORTED_FORMAT;
286         }
287
288         mm_util_debug("format: %d, *imgsize: %d", format, *imgsize);
289
290         return ret;
291 }
292
293 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)
294 {
295         int ret = MM_UTIL_ERROR_NONE;
296
297         mm_util_retvm_if(_imgp_info_s == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid _imgp_info_s");
298
299         _imgp_info_s->src_format = src_format;
300         _imgp_info_s->src_width = src_width;
301         _imgp_info_s->src_height = src_height;
302
303         _imgp_info_s->dst_format = dst_format;
304         _imgp_info_s->dst_width = dst_width;
305         _imgp_info_s->dst_height = dst_height;
306         _imgp_info_s->buffer_size = 0;
307         _imgp_info_s->angle = angle;
308
309         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);
310
311         return ret;
312 }
313
314 static GModule *__mm_util_imgp_initialize(imgp_plugin_type_e _imgp_plugin_type_e)
315 {
316         GModule *module = NULL;
317         mm_util_fenter();
318
319         if (_imgp_plugin_type_e == IMGP_NEON)
320                 module = g_module_open(PATH_NEON_LIB, G_MODULE_BIND_LAZY);
321         else if (_imgp_plugin_type_e == IMGP_GSTCS)
322                 module = g_module_open(PATH_GSTCS_LIB, G_MODULE_BIND_LAZY);
323
324         mm_util_retvm_if(module == NULL, NULL, "[%d] %s | %s module open failed", _imgp_plugin_type_e, PATH_NEON_LIB, PATH_GSTCS_LIB);
325         mm_util_debug("module: %p, g_module_name: %s", module, g_module_name(module));
326
327         return module;
328 }
329
330 static void __mm_util_imgp_finalize(GModule *module, imgp_info_s *_imgp_info_s)
331 {
332         if (module)
333                 g_module_close(module);
334
335         MMUTIL_SAFE_FREE(_imgp_info_s);
336
337         return;
338 }
339
340 static int __mm_util_crop_rgba32(const unsigned char *src, unsigned int src_width, unsigned int src_height,
341 unsigned int crop_start_x, unsigned int crop_start_y, unsigned int crop_dest_width, unsigned int crop_dest_height, unsigned char *dst)
342 {
343         int ret = MM_UTIL_ERROR_NONE;
344         unsigned int idx = 0;
345         int src_bytesperline = src_width * 4;
346         int dst_bytesperline = crop_dest_width * 4;
347
348         src += crop_start_y * src_bytesperline + 4 * crop_start_x;
349
350         for (idx = 0; idx < crop_dest_height; idx++) {
351                 memcpy(dst, src, dst_bytesperline);
352                 src += src_bytesperline;
353                 dst += dst_bytesperline;
354         }
355
356         return ret;
357 }
358
359 static int __mm_util_crop_rgb888(const unsigned char *src, unsigned int src_width, unsigned int src_height,
360 unsigned int crop_start_x, unsigned int crop_start_y, unsigned int crop_dest_width, unsigned int crop_dest_height, unsigned char *dst)
361 {
362         int ret = MM_UTIL_ERROR_NONE;
363         unsigned int idx = 0;
364         int src_bytesperline = src_width * 3;
365         int dst_bytesperline = crop_dest_width * 3;
366
367         src += crop_start_y * src_bytesperline + 3 * crop_start_x;
368
369         for (idx = 0; idx < crop_dest_height; idx++) {
370                 memcpy(dst, src, dst_bytesperline);
371                 src += src_bytesperline;
372                 dst += dst_bytesperline;
373         }
374
375         return ret;
376 }
377
378 static int __mm_util_crop_rgb565(const unsigned char *src, unsigned int src_width, unsigned int src_height,
379 unsigned int crop_start_x, unsigned int crop_start_y, unsigned int crop_dest_width, unsigned int crop_dest_height, unsigned char *dst)
380 {
381         int ret = MM_UTIL_ERROR_NONE;
382         unsigned int idx = 0;
383         int src_bytesperline = src_width * 2;
384         int dst_bytesperline = crop_dest_width * 2;
385
386         src += crop_start_y * src_bytesperline + 2 * crop_start_x;
387
388         for (idx = 0; idx < crop_dest_height; idx++) {
389                 memcpy(dst, src, dst_bytesperline);
390                 src += src_bytesperline;
391                 dst += dst_bytesperline;
392         }
393
394         return ret;
395 }
396
397 static int __mm_util_crop_yuv420(const unsigned char *src, unsigned int src_width, unsigned int src_height,
398 unsigned int crop_start_x, unsigned int crop_start_y, unsigned int crop_dest_width, unsigned int crop_dest_height, unsigned char *dst)
399 {
400         int ret = MM_UTIL_ERROR_NONE;
401         unsigned int idx = 0;
402         int start_x = crop_start_x;
403         int start_y = crop_start_y;
404
405         const unsigned char *_src = src + start_y * src_width + start_x;
406
407         /* Y */
408         for (idx = 0; idx < crop_dest_height; idx++) {
409                 memcpy(dst, _src, crop_dest_width);
410                 _src += src_width;
411                 dst += crop_dest_width;
412         }
413
414         /* U */
415         _src = src + src_height * src_width + (start_y / 2) * src_width / 2 + start_x / 2;
416         for (idx = 0; idx < crop_dest_height / 2; idx++) {
417                 memcpy(dst, _src, crop_dest_width / 2);
418                 _src += src_width / 2;
419                 dst += crop_dest_width / 2;
420         }
421
422         /* V */
423         _src = src + src_height * src_width * 5 / 4 + (start_y / 2) * src_width / 2 + start_x / 2;
424         for (idx = 0; idx < crop_dest_height / 2; idx++) {
425                 memcpy(dst, _src, crop_dest_width / 2);
426                 _src += src_width / 2;
427                 dst += crop_dest_width / 2;
428         }
429
430         return ret;
431 }
432
433 static int __mm_util_handle_init(mm_util_s *handle)
434 {
435         int ret = MM_UTIL_ERROR_NONE;
436
437         mm_util_retvm_if(handle == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid handle");
438
439         /* private values init */
440         handle->dst = NULL;
441         handle->dst_format = MM_UTIL_COLOR_NUM;
442         handle->rotation = MM_UTIL_ROTATION_NONE;
443
444         handle->start_x = -1;
445         handle->start_y = -1;
446         handle->dst_width = 0;
447         handle->dst_height = 0;
448         handle->is_completed = FALSE;
449         handle->is_finish = FALSE;
450
451         handle->set_convert = FALSE;
452         handle->set_crop = FALSE;
453         handle->set_resize = FALSE;
454         handle->set_rotate = FALSE;
455
456         /*These are a communicator for thread*/
457         if (!handle->queue)
458                 handle->queue = g_async_queue_new();
459
460         if (handle->queue == NULL) {
461                 mm_util_error("g_async_queue_new failed");
462                 return MM_UTIL_ERROR_INVALID_OPERATION;
463         }
464
465         return ret;
466 }
467
468 gpointer _mm_util_thread_repeate(gpointer data)
469 {
470         mm_util_s *handle = (mm_util_s *) data;
471         int ret = MM_UTIL_ERROR_NONE;
472         mm_util_color_image_h pop_data = NULL;
473
474         mm_util_retvm_if(handle == NULL, NULL, "invalid handle");
475
476         while (!handle->is_finish) {
477                 mm_util_debug("waiting...");
478                 pop_data = (mm_util_color_image_h)g_async_queue_timeout_pop(handle->queue, 300 * G_TIME_SPAN_MILLISECOND);
479                 mm_util_debug("get from data or timeout");
480
481                 if (pop_data == NULL) {
482                         mm_util_error("The data is null");
483                         continue;
484                 }
485
486                 ret = __mm_util_transform_exec(handle, (color_image_data_s *)pop_data); /* Need to block */
487                 if (ret == MM_UTIL_ERROR_NONE)
488                         mm_util_debug("Success - transform_exec");
489                 else
490                         mm_util_error("Error - transform_exec");
491
492                 if (handle->_util_cb->completed_cb) {
493                         mm_util_debug("completed_cb is called");
494                         handle->_util_cb->completed_cb(handle->dst, ret, handle->_util_cb->user_data);
495                 }
496                 mm_util_destroy_color_image(pop_data);
497                 mm_util_destroy_color_image(handle->dst);
498                 handle->is_completed = FALSE;
499         }
500
501         mm_util_debug("exit thread");
502         handle->thread = NULL;
503
504         return NULL;
505 }
506
507 static int __mm_util_create_thread(mm_util_s *handle)
508 {
509         int ret = MM_UTIL_ERROR_NONE;
510
511         mm_util_retvm_if(handle == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid handle");
512         mm_util_retvm_if(handle->thread != NULL, MM_UTIL_ERROR_NONE, "[NO-ERROR] Thread is already created");
513
514         /*create threads*/
515         handle->thread = g_thread_new("transform_thread", (GThreadFunc)_mm_util_thread_repeate, (gpointer)handle);
516         mm_util_retvm_if(handle->thread == NULL, MM_UTIL_ERROR_INVALID_OPERATION, "ERROR - create thread");
517
518         mm_util_debug("New thread is created");
519
520         return ret;
521 }
522
523 static int __mm_util_processing(mm_util_s *handle)
524 {
525         int ret = MM_UTIL_ERROR_NONE;
526         unsigned char *dst_buf[4] = {NULL,};
527         unsigned int src_width = 0, src_height = 0;
528         mm_util_color_format_e src_format = -1;
529         unsigned int src_index = 0, dst_index = 0;
530         unsigned int res_w = 0;
531         unsigned int res_h = 0;
532         unsigned char *res_buffer = NULL;
533         size_t res_buffer_size = 0;
534
535         mm_util_retvm_if(handle == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid handle");
536
537         mm_util_debug("src: %p, dst: %p", handle->src, handle->dst);
538
539         dst_buf[src_index] = calloc(1, handle->src->size);
540         src_width = handle->src->width;
541         src_height = handle->src->height;
542         src_format = handle->src->color;
543         if (dst_buf[src_index] == NULL) {
544                 mm_util_error("[multi func] memory allocation error");
545                 return MM_UTIL_ERROR_INVALID_OPERATION;
546         }
547         memcpy(dst_buf[src_index], handle->src->data, handle->src->size);
548
549         if (handle->set_crop) {
550                 dst_index++;
551
552                 ret = mm_util_crop_image(dst_buf[src_index], src_width, src_height, src_format, handle->start_x, handle->start_y, handle->dst_width, handle->dst_height, &res_buffer, &res_w, &res_h, &res_buffer_size);
553                 if (ret != MM_UTIL_ERROR_NONE) {
554                         __mm_destroy_temp_buffer(dst_buf);
555                         mm_util_error("mm_util_crop_image failed");
556                         return ret;
557                 }
558                 dst_buf[dst_index] = res_buffer;
559
560                 src_index = dst_index;
561                 src_width = res_w;
562                 src_height = res_h;
563         } else if (handle->set_resize) {
564                 dst_index++;
565
566                 ret = mm_util_resize_image(dst_buf[src_index], src_width, src_height, src_format, handle->dst_width, handle->dst_height, &res_buffer, &res_w, &res_h, &res_buffer_size);
567                 if (ret != MM_UTIL_ERROR_NONE) {
568                         __mm_destroy_temp_buffer(dst_buf);
569                         mm_util_error("mm_util_resize_image failed");
570                         return ret;
571                 }
572
573                 dst_buf[dst_index] = res_buffer;
574                 src_index = dst_index;
575                 src_width = res_w;
576                 src_height = res_h;
577         }
578
579         if (handle->set_convert) {
580                 dst_index++;
581
582                 mm_util_get_image_size(handle->dst_format, src_width, src_height, &res_buffer_size);
583                 dst_buf[dst_index] = calloc(1, res_buffer_size);
584                 if (dst_buf[dst_index] == NULL) {
585                         mm_util_error("[multi func] memory allocation error");
586                         __mm_destroy_temp_buffer(dst_buf);
587                         return MM_UTIL_ERROR_INVALID_OPERATION;
588                 }
589                 ret = mm_util_convert_colorspace(dst_buf[src_index], src_width, src_height, src_format, dst_buf[dst_index], handle->dst_format);
590                 if (ret != MM_UTIL_ERROR_NONE) {
591                         __mm_destroy_temp_buffer(dst_buf);
592                         mm_util_error("mm_util_convert_colorspace failed");
593                         return ret;
594                 }
595                 src_index = dst_index;
596                 src_format = handle->dst_format;
597         }
598
599         if (handle->set_rotate) {
600                 dst_index++;
601                 ret = mm_util_rotate_image(dst_buf[src_index], src_width, src_height, src_format, handle->rotation, &res_buffer, &res_w, &res_h, &res_buffer_size);
602                 if (ret != MM_UTIL_ERROR_NONE) {
603                         __mm_destroy_temp_buffer(dst_buf);
604                         mm_util_error("mm_util_rotate_image failed");
605                         return ret;
606                 }
607
608                 dst_buf[dst_index] = res_buffer;
609                 src_index = dst_index;
610                 src_width = res_w;
611                 src_height = res_h;
612         }
613
614         if (dst_buf[dst_index] != NULL && res_buffer_size != 0) {
615                 ret = mm_util_create_color_image((mm_util_color_image_h *)&(handle->dst), (unsigned long)src_width, (unsigned long)src_height, src_format, (void *)dst_buf[dst_index], (size_t)res_buffer_size);
616                 if (ret != MM_UTIL_ERROR_NONE)
617                         mm_util_error("mm_util_set_color_image failed");
618         }
619         __mm_destroy_temp_buffer(dst_buf);
620
621         mm_util_error("mm_util_processing was finished");
622
623         return ret;
624 }
625
626 static int __mm_util_transform_exec(mm_util_s *handle, color_image_data_s *source_image)
627 {
628         int ret = MM_UTIL_ERROR_NONE;
629
630         mm_util_retvm_if(handle == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid handle");
631         mm_util_retvm_if(source_image == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid source_image");
632
633         mm_util_debug("orig_image: %p [%zu] %lu X %lu (%u)", source_image->data, source_image->size,
634                 source_image->width, source_image->height, source_image->color);
635
636         handle->src = source_image;
637         handle->dst = NULL;
638
639         ret = __mm_util_processing(handle);
640         if (ret != MM_UTIL_ERROR_NONE) {
641                 mm_util_error("__mm_util_processing failed (%d)", ret);
642                 return ret;
643         }
644
645         mm_util_debug("result_image: %p [%zu] %lu X %lu (%u)", handle->dst->data, handle->dst->size,
646                 handle->dst->width, handle->dst->height, handle->dst->color);
647
648         return ret;
649 }
650
651 static int
652 _mm_util_handle_finalize(mm_util_s *handle)
653 {
654         int ret = MM_UTIL_ERROR_NONE;
655
656         mm_util_retvm_if(handle == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid handle");
657
658         /* g_thread_exit(handle->thread); */
659         if (handle->thread) {
660                 handle->is_finish = TRUE;
661                 g_thread_join(handle->thread);
662         }
663
664         if (handle->queue) {
665                 g_async_queue_unref(handle->queue);
666                 handle->queue = NULL;
667         }
668
669         mm_util_debug("Success - Finalize Handle");
670
671         return ret;
672 }
673
674 int mm_util_create(mm_util_imgp_h *imgp_handle)
675 {
676         int ret = MM_UTIL_ERROR_NONE;
677
678         mm_util_retvm_if(imgp_handle == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid imgp_handle");
679
680         mm_util_s *handle = calloc(1, sizeof(mm_util_s));
681         if (!handle) {
682                 mm_util_error("[ERROR] - _handle");
683                 return MM_UTIL_ERROR_INVALID_OPERATION;
684         }
685
686         ret = __mm_util_handle_init(handle);
687         if (ret != MM_UTIL_ERROR_NONE) {
688                 mm_util_error("_mm_util_handle_init failed");
689                 MMUTIL_SAFE_FREE(handle);
690                 return ret;
691         }
692
693         *imgp_handle = (mm_util_imgp_h)handle;
694
695         return ret;
696 }
697
698 int mm_util_set_colorspace_convert(mm_util_imgp_h imgp_handle, mm_util_color_format_e colorspace)
699 {
700         int ret = MM_UTIL_ERROR_NONE;
701         mm_util_s *handle = (mm_util_s *) imgp_handle;
702
703         mm_util_retvm_if(handle == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid handle");
704
705         handle->set_convert = TRUE;
706         handle->dst_format = colorspace;
707         mm_util_debug("imgp fmt: %d", handle->dst_format);
708
709         return ret;
710 }
711
712 int mm_util_set_resolution(mm_util_imgp_h imgp_handle, unsigned int width, unsigned int height)
713 {
714         int ret = MM_UTIL_ERROR_NONE;
715         mm_util_s *handle = (mm_util_s *) imgp_handle;
716
717         mm_util_retvm_if(handle == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid handle");
718
719         handle->set_resize = TRUE;
720         handle->dst_width = width;
721         handle->dst_height = height;
722
723         return ret;
724 }
725
726 int mm_util_set_rotation(mm_util_imgp_h imgp_handle, mm_util_img_rotate_type rotation)
727 {
728         int ret = MM_UTIL_ERROR_NONE;
729         mm_util_s *handle = (mm_util_s *) imgp_handle;
730
731         mm_util_retvm_if(handle == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid handle");
732
733         handle->set_rotate = TRUE;
734         handle->rotation = rotation;
735
736         return ret;
737 }
738
739 int mm_util_set_crop_area(mm_util_imgp_h imgp_handle, unsigned int start_x, unsigned int start_y, unsigned int end_x, unsigned int end_y)
740 {
741         int ret = MM_UTIL_ERROR_NONE;
742         mm_util_s *handle = (mm_util_s *) imgp_handle;
743
744         unsigned int dest_width = end_x - start_x;
745         unsigned int dest_height = end_y - start_y;
746
747         mm_util_retvm_if(handle == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid handle");
748
749         handle->set_crop = TRUE;
750         handle->start_x = start_x;
751         handle->start_y = start_y;
752         handle->dst_width = dest_width;
753         handle->dst_height = dest_height;
754
755         return ret;
756 }
757
758 int mm_util_transform(mm_util_imgp_h imgp_handle, mm_util_color_image_h image, mm_util_completed_callback completed_callback, void *user_data)
759 {
760         int ret = MM_UTIL_ERROR_NONE;
761         mm_util_s *handle = (mm_util_s *) imgp_handle;
762
763         mm_util_fenter();
764
765         mm_util_retvm_if(handle == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid handle");
766         mm_util_retvm_if(image == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid image");
767         mm_util_retvm_if(completed_callback == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid completed_callback");
768
769         mm_util_debug("image: %p", image);
770
771         MMUTIL_SAFE_FREE(handle->_util_cb);
772         handle->_util_cb = (mm_util_cb_s *)calloc(1, sizeof(mm_util_cb_s));
773         if (handle->_util_cb) {
774                 handle->_util_cb->completed_cb = completed_callback;
775                 handle->_util_cb->user_data = user_data;
776         } else {
777                 mm_util_error("[ERROR] _util_cb_s");
778         }
779
780         if (handle->queue) {
781                 mm_util_debug("g_async_queue_push");
782                 g_async_queue_push(handle->queue, GINT_TO_POINTER(image));
783                 ret = __mm_util_create_thread(handle);
784                 if (ret != MM_UTIL_ERROR_NONE) {
785                         mm_util_error("ERROR - Create thread");
786                         return ret;
787                 } else {
788                         mm_util_debug("Success -__mm_util_create_thread");
789                 }
790         }
791
792         mm_util_fleave();
793
794         return ret;
795 }
796
797 int mm_util_transform_is_completed(mm_util_imgp_h imgp_handle, bool *is_completed)
798 {
799         int ret = MM_UTIL_ERROR_NONE;
800
801         mm_util_s *handle = (mm_util_s *) imgp_handle;
802
803         mm_util_retvm_if(handle == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid handle");
804         mm_util_retvm_if(!is_completed, MM_UTIL_ERROR_INVALID_PARAMETER, "[ERROR] - is_completed");
805
806         *is_completed = handle->is_completed;
807         mm_util_debug("[Transform....] %d", *is_completed);
808
809         return ret;
810 }
811
812 int mm_util_destroy(mm_util_imgp_h imgp_handle)
813 {
814         int ret = MM_UTIL_ERROR_NONE;
815         mm_util_s *handle = (mm_util_s *) imgp_handle;
816
817         mm_util_fenter();
818
819         mm_util_retvm_if(handle == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid handle");
820         mm_util_retvm_if(_mm_util_handle_finalize(handle) != MM_UTIL_ERROR_NONE, MM_UTIL_ERROR_INVALID_PARAMETER, "fail _mm_util_handle_finalize");
821
822         MMUTIL_SAFE_FREE(handle->_util_cb);
823         MMUTIL_SAFE_FREE(handle);
824
825         mm_util_fleave();
826
827         return ret;
828 }
829
830 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)
831 {
832         imgp_plugin_type_e _imgp_plugin_type_e = IMGP_GSTCS;
833         GModule *_module = NULL;
834         IMGPInfoFunc _func = NULL;
835
836         if (function == IMGP_CSC) {
837                 if (__mm_select_convert_plugin(src_format, dst_format))
838                         _imgp_plugin_type_e = IMGP_NEON;
839
840         } else if (function == IMGP_RSZ) {
841                 if (__mm_select_resize_plugin(src_format))
842                         _imgp_plugin_type_e = IMGP_NEON;
843
844         } else if (function == IMGP_ROT) {
845                 if (__mm_select_rotate_plugin(src_format))
846                         _imgp_plugin_type_e = IMGP_NEON;
847
848         } else {
849                 mm_util_error("invalid function : [%d]", function);
850         }
851
852         mm_util_debug("plugin type: %d", _imgp_plugin_type_e);
853
854         _module = __mm_util_imgp_initialize(_imgp_plugin_type_e);
855
856         if (_module == NULL) { /* when IMGP_NEON is NULL */
857                 _imgp_plugin_type_e = IMGP_GSTCS;
858                 mm_util_debug("You use %s module", PATH_GSTCS_LIB);
859                 _module = __mm_util_imgp_initialize(_imgp_plugin_type_e);
860         }
861
862         mm_util_debug("mm_util_imgp_func: %p", _module);
863
864         if (_module == NULL) {
865                 mm_util_error("invalid module");
866                 return NULL;
867         }
868
869         g_module_symbol(_module, IMGP_FUNC_NAME, (gpointer *)&_func);
870
871         if (_func == NULL) {
872                 mm_util_error("invalid function");
873                 g_module_close(_module);
874                 return NULL;
875         }
876
877         *module = _module;
878
879         return _func;
880 }
881
882 static bool __mm_util_check_format(mm_util_color_format_e color_format)
883 {
884         if ((color_format >= MM_UTIL_COLOR_YUV420) && (color_format <= MM_UTIL_COLOR_BGRX))
885                 return TRUE;
886
887         return FALSE;
888 }
889
890 int mm_util_convert_colorspace(const unsigned char *src, unsigned int src_width, unsigned int src_height, mm_util_color_format_e src_format, unsigned char *dst, mm_util_color_format_e dst_format)
891 {
892         int ret = MM_UTIL_ERROR_NONE;
893         IMGPInfoFunc _mm_util_imgp_func = NULL;
894         GModule *_module = NULL;
895         unsigned char *output_buffer = NULL;
896         unsigned int res_w = 0;
897         unsigned int res_h = 0;
898         unsigned char *res_buffer = NULL;
899         size_t res_buffer_size = 0;
900
901         mm_util_retvm_if(src == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid src");
902         mm_util_retvm_if(dst == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid dst");
903         mm_util_retvm_if((IS_MM_UTIL_COLOR_FORMAT(src_format) == FALSE), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid src_format [%d]", src_format);
904         mm_util_retvm_if((IS_MM_UTIL_COLOR_FORMAT(dst_format) == FALSE), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid dst_format [%d]", dst_format);
905         mm_util_retvm_if((__mm_util_check_format(src_format) == FALSE), MM_UTIL_ERROR_NOT_SUPPORTED_FORMAT, "not supported src_format [%d]", src_format);
906         mm_util_retvm_if((__mm_util_check_format(dst_format) == FALSE), MM_UTIL_ERROR_NOT_SUPPORTED_FORMAT, "not supported dst_format [%d]", dst_format);
907
908         mm_util_debug("src_width [%d] src_height [%d] src_format[%d] dst_format[%d]", src_width, src_height, src_format, dst_format);
909
910         _mm_util_imgp_func = __mm_util_initialize(IMGP_CSC, src_format, dst_format, &_module);
911         if (_mm_util_imgp_func == NULL) {
912                 mm_util_error("ERROR - __mm_util_initialize");
913                 return MM_UTIL_ERROR_INVALID_OPERATION;
914         }
915
916         imgp_info_s *_imgp_info_s = (imgp_info_s *) calloc(1, sizeof(imgp_info_s));
917         if (_imgp_info_s == NULL) {
918                 mm_util_error("ERROR - alloc handle");
919                 ret = MM_UTIL_ERROR_OUT_OF_MEMORY;
920                 goto ERROR;
921         }
922
923         ret = __mm_set_imgp_info_s(_imgp_info_s, src_format, src_width, src_height, dst_format, src_width, src_height, MM_UTIL_ROTATE_0);
924         if (ret != MM_UTIL_ERROR_NONE) {
925                 mm_util_error("__mm_set_imgp_info_s failed");
926                 ret = MM_UTIL_ERROR_INVALID_OPERATION;
927                 goto ERROR;
928         }
929
930         ret = _mm_util_imgp_func(_imgp_info_s, src, &output_buffer, IMGP_CSC);
931         if (ret != MM_UTIL_ERROR_NONE) {
932                 mm_util_error("image processing failed");
933                 goto ERROR;
934         }
935
936         if ((_imgp_info_s->dst_width != _imgp_info_s->output_stride || _imgp_info_s->dst_height != _imgp_info_s->output_elevation)) {
937                 ret = mm_util_crop_image(output_buffer, _imgp_info_s->output_stride, _imgp_info_s->output_elevation, dst_format, 0, 0, _imgp_info_s->dst_width, _imgp_info_s->dst_height, &res_buffer, &res_w, &res_h, &res_buffer_size);
938                 if (ret != MM_UTIL_ERROR_NONE) {
939                         mm_util_error("mm_util_crop_image failed");
940                         ret = MM_UTIL_ERROR_INVALID_OPERATION;
941                         goto ERROR;
942                 }
943                 memcpy(dst, res_buffer, res_buffer_size);
944         } else {
945                 memcpy(dst, output_buffer, _imgp_info_s->buffer_size);
946         }
947
948         /* Output result*/
949         mm_util_debug("dst[%p] dst_width[%u] dst_height[%u] output_stride[%u] output_elevation[%u]",
950                         dst, _imgp_info_s->dst_width, _imgp_info_s->dst_height, _imgp_info_s->output_stride, _imgp_info_s->output_elevation);
951
952 ERROR:
953         /* Finalize */
954         __mm_util_imgp_finalize(_module, _imgp_info_s);
955
956         MMUTIL_SAFE_FREE(output_buffer);
957         MMUTIL_SAFE_FREE(res_buffer);
958
959         mm_util_fleave();
960
961         return ret;
962 }
963
964 int mm_util_resize_image(const unsigned char *src, unsigned int src_width, unsigned int src_height, mm_util_color_format_e src_format, unsigned int dst_width, unsigned int dst_height, unsigned char **dst, unsigned int *result_buf_width, unsigned int *result_buf_height, size_t *result_buf_size)
965 {
966         int ret = MM_UTIL_ERROR_NONE;
967         IMGPInfoFunc _mm_util_imgp_func = NULL;
968         GModule *_module = NULL;
969         unsigned char *output_buffer = NULL;
970         unsigned int res_w = 0;
971         unsigned int res_h = 0;
972         unsigned char *res_buffer = NULL;
973         size_t res_buffer_size = 0;
974
975         mm_util_retvm_if(src == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid src");
976         mm_util_retvm_if(src_width == 0, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid src_width");
977         mm_util_retvm_if(src_height == 0, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid src_height");
978         mm_util_retvm_if((IS_MM_UTIL_COLOR_FORMAT(src_format) == FALSE), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid src_format [%d]", src_format);
979         mm_util_retvm_if((__mm_util_check_format(src_format) == FALSE), MM_UTIL_ERROR_NOT_SUPPORTED_FORMAT, "not supported src_format [%d]", src_format);
980         mm_util_retvm_if(dst == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid dst");
981         mm_util_retvm_if(dst_width == 0, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid dst_width");
982         mm_util_retvm_if(dst_height == 0, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid dst_height");
983
984         mm_util_debug("src_width [%d] src_height [%d] src_format[%d]", src_width, src_height, src_format);
985
986         _mm_util_imgp_func = __mm_util_initialize(IMGP_RSZ, src_format, 0, &_module);
987         mm_util_retvm_if(_mm_util_imgp_func == NULL, MM_UTIL_ERROR_INVALID_OPERATION, "fail __mm_util_initialize");
988
989         imgp_info_s *_imgp_info_s = (imgp_info_s *) calloc(1, sizeof(imgp_info_s));
990         if (_imgp_info_s == NULL) {
991                 mm_util_error("ERROR - alloc handle");
992                 ret = MM_UTIL_ERROR_OUT_OF_MEMORY;
993                 goto ERROR;
994         }
995
996         res_w = dst_width;
997         res_h = dst_height;
998
999         ret = __mm_set_imgp_info_s(_imgp_info_s, src_format, src_width, src_height, src_format, dst_width, dst_height, MM_UTIL_ROTATE_0);
1000         if (ret != MM_UTIL_ERROR_NONE) {
1001                 mm_util_error("__mm_set_imgp_info_s failed [%d]", ret);
1002                 ret = MM_UTIL_ERROR_INVALID_OPERATION;
1003                 goto ERROR;
1004         }
1005
1006         if (g_strrstr(g_module_name(_module), GST)) {
1007                 if (__mm_gst_can_resize_format(_imgp_info_s->src_format) == FALSE) {
1008                         mm_util_error("#RESIZE ERROR# IMAGE_NOT_SUPPORT_FORMAT");
1009                         ret = MM_UTIL_ERROR_NOT_SUPPORTED_FORMAT;
1010                         goto ERROR;
1011                 }
1012         }
1013
1014         ret = _mm_util_imgp_func(_imgp_info_s, src, &output_buffer, IMGP_RSZ);
1015         mm_util_debug("_mm_util_imgp_func, ret: %d", ret);
1016         if (ret != MM_UTIL_ERROR_NONE) {
1017                 mm_util_error("image processing failed");
1018                 goto ERROR;
1019         }
1020
1021         if ((_imgp_info_s->dst_width != _imgp_info_s->output_stride || _imgp_info_s->dst_height != _imgp_info_s->output_elevation)) {
1022                 ret = mm_util_crop_image(output_buffer, _imgp_info_s->output_stride, _imgp_info_s->output_elevation, src_format, 0, 0, _imgp_info_s->dst_width, _imgp_info_s->dst_height, &res_buffer, &res_w, &res_h, &res_buffer_size);
1023                 if (ret != MM_UTIL_ERROR_NONE) {
1024                         mm_util_error("mm_util_crop_image failed");
1025                         MMUTIL_SAFE_FREE(output_buffer);
1026                         ret = MM_UTIL_ERROR_INVALID_OPERATION;
1027                         goto ERROR;
1028                 }
1029
1030                 MMUTIL_SAFE_FREE(output_buffer);
1031                 *dst = res_buffer;
1032                 *result_buf_size = res_buffer_size;
1033
1034         } else {
1035                 *dst = output_buffer;
1036                 *result_buf_size = _imgp_info_s->buffer_size;
1037         }
1038
1039         *result_buf_width = res_w;
1040         *result_buf_height = res_h;
1041
1042         mm_util_debug("dst[%p] result_buf_w[%u] result_buf_h[%u] output_stride[%u] output_elevation[%u]", dst, *result_buf_width, *result_buf_height, _imgp_info_s->output_stride, _imgp_info_s->output_elevation);
1043
1044 ERROR:
1045         /* Finalize */
1046         __mm_util_imgp_finalize(_module, _imgp_info_s);
1047
1048         mm_util_fleave();
1049
1050         return ret;
1051 }
1052
1053 int mm_util_rotate_image(const unsigned char *src, unsigned int src_width, unsigned int src_height, mm_util_color_format_e src_format, mm_util_img_rotate_type angle, unsigned char **dst, unsigned int *result_buf_width, unsigned int *result_buf_height, size_t *result_buf_size)
1054 {
1055         int ret = MM_UTIL_ERROR_NONE;
1056         IMGPInfoFunc _mm_util_imgp_func = NULL;
1057         GModule *_module = NULL;
1058         unsigned char *output_buffer = NULL;
1059         unsigned int res_w = 0;
1060         unsigned int res_h = 0;
1061         unsigned char *res_buffer = NULL;
1062         size_t res_buffer_size = 0;
1063
1064         mm_util_retvm_if(src == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid src");
1065         mm_util_retvm_if(src_width == 0, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid src_width");
1066         mm_util_retvm_if(src_height == 0, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid src_height");
1067         mm_util_retvm_if((IS_MM_UTIL_COLOR_FORMAT(src_format) == FALSE), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid src_format [%d]", src_format);
1068         mm_util_retvm_if((__mm_util_check_format(src_format) == FALSE), MM_UTIL_ERROR_NOT_SUPPORTED_FORMAT, "not supported src_format [%d]", src_format);
1069         mm_util_retvm_if((angle < MM_UTIL_ROTATE_0) || (angle >= MM_UTIL_ROTATE_NUM), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid angle [%d]", angle);
1070         mm_util_retvm_if(dst == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid dst");
1071         mm_util_retvm_if(result_buf_width == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid result_buf_width");
1072         mm_util_retvm_if(result_buf_height == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid result_buf_height");
1073         mm_util_retvm_if(result_buf_size == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid result_buf_size");
1074
1075         mm_util_debug("src_w[%u] src_h[%u] src_format[%u] angle[%u]", src_width, src_height, src_format, angle);
1076
1077         _mm_util_imgp_func = __mm_util_initialize(IMGP_ROT, src_format, 0, &_module);
1078         if (_mm_util_imgp_func == NULL) {
1079                 mm_util_error("ERROR - __mm_util_initialize");
1080                 return MM_UTIL_ERROR_INVALID_OPERATION;
1081         }
1082
1083         imgp_info_s *_imgp_info_s = (imgp_info_s *) calloc(1, sizeof(imgp_info_s));
1084         if (_imgp_info_s == NULL) {
1085                 mm_util_error("ERROR - alloc handle");
1086                 ret = MM_UTIL_ERROR_OUT_OF_MEMORY;
1087                 goto ERROR;
1088         }
1089
1090         if ((angle == MM_UTIL_ROTATE_90) || (angle == MM_UTIL_ROTATE_270)) {
1091                 res_w = src_height;
1092                 res_h = src_width;
1093         } else {
1094                 res_w = src_width;
1095                 res_h = src_height;
1096         }
1097
1098         ret = __mm_set_imgp_info_s(_imgp_info_s, src_format, src_width, src_height, src_format, res_w, res_h, angle);
1099         mm_util_debug("__mm_set_imgp_info_s");
1100         if (ret != MM_UTIL_ERROR_NONE) {
1101                 mm_util_error("__mm_set_imgp_info_s failed");
1102                 ret = MM_UTIL_ERROR_INVALID_OPERATION;
1103                 goto ERROR;
1104         }
1105
1106         if (g_strrstr(g_module_name(_module), GST)) {
1107                 if (__mm_gst_can_rotate_format(_imgp_info_s->src_format) == FALSE) {
1108                         mm_util_error("#gstreamer ROTATE ERROR# IMAGE_NOT_SUPPORT_FORMAT");
1109                         ret = MM_UTIL_ERROR_NOT_SUPPORTED_FORMAT;
1110                         goto ERROR;
1111                 }
1112         }
1113
1114         ret = _mm_util_imgp_func(_imgp_info_s, src, &output_buffer, IMGP_ROT);
1115         if (ret != MM_UTIL_ERROR_NONE) {
1116                 mm_util_error("image processing failed");
1117                 goto ERROR;
1118         }
1119
1120         if ((_imgp_info_s->dst_width != _imgp_info_s->output_stride || _imgp_info_s->dst_height != _imgp_info_s->output_elevation)) {
1121                 unsigned int start_x = 0;
1122                 unsigned int start_y = 0;
1123                 if (angle == MM_UTIL_ROTATE_90) {
1124                         start_x = 0;
1125                         start_y = 0;
1126                 } else if (angle == MM_UTIL_ROTATE_180) {
1127                         start_x = _imgp_info_s->output_stride-_imgp_info_s->dst_width;
1128                         start_y = 0;
1129                 } else if (angle == MM_UTIL_ROTATE_270) {
1130                         start_x = 0;
1131                         start_y = _imgp_info_s->output_elevation - _imgp_info_s->dst_height;
1132                 }
1133                 ret = mm_util_crop_image(output_buffer, _imgp_info_s->output_stride, _imgp_info_s->output_elevation, src_format, start_x, start_y, _imgp_info_s->dst_width, _imgp_info_s->dst_height, &res_buffer, &res_w, &res_h, &res_buffer_size);
1134                 if (ret != MM_UTIL_ERROR_NONE) {
1135                         mm_util_error("mm_util_crop_image failed");
1136                         MMUTIL_SAFE_FREE(output_buffer);
1137                         ret = MM_UTIL_ERROR_INVALID_OPERATION;
1138                         goto ERROR;
1139                 }
1140
1141                 MMUTIL_SAFE_FREE(output_buffer);
1142                 *dst = res_buffer;
1143                 *result_buf_size = res_buffer_size;
1144         } else {
1145                 *dst = output_buffer;
1146                 *result_buf_size = _imgp_info_s->buffer_size;
1147         }
1148
1149         *result_buf_width = res_w;
1150         *result_buf_height = res_h;
1151
1152         mm_util_debug("dst[%p] result_buf_w[%u] result_buf_h[%u] output_stride[%u] output_elevation[%u]", dst, *result_buf_width, *result_buf_height, _imgp_info_s->output_stride, _imgp_info_s->output_elevation);
1153
1154 ERROR:
1155         /* Finalize */
1156         __mm_util_imgp_finalize(_module, _imgp_info_s);
1157
1158         mm_util_fleave();
1159
1160         return ret;
1161 }
1162
1163 int mm_util_crop_image(const unsigned char *src, unsigned int src_width, unsigned int src_height, mm_util_color_format_e src_format,
1164 unsigned int crop_start_x, unsigned int crop_start_y, unsigned int crop_dest_width, unsigned int crop_dest_height, unsigned char **dst, unsigned int *result_buf_width, unsigned int *result_buf_height, size_t *result_buf_size)
1165 {
1166         int ret = MM_UTIL_ERROR_NONE;
1167         unsigned int dst_buf_size = 0;
1168         unsigned char *dst_buffer = NULL;
1169         unsigned int res_w = 0;
1170         unsigned int res_h = 0;
1171
1172         mm_util_retvm_if(src == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid src");
1173         mm_util_retvm_if(src_width == 0, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid src_width");
1174         mm_util_retvm_if(src_height == 0, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid src_height");
1175         mm_util_retvm_if((IS_MM_UTIL_COLOR_FORMAT(src_format) == FALSE), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid src_format [%d]", src_format);
1176         mm_util_retvm_if((__mm_util_check_format(src_format) == FALSE), MM_UTIL_ERROR_NOT_SUPPORTED_FORMAT, "not supported src_format [%d]", src_format);
1177         mm_util_retvm_if(dst == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid dst");
1178         mm_util_retvm_if(result_buf_width == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid result_buf_width");
1179         mm_util_retvm_if(result_buf_height == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid result_buf_height");
1180         mm_util_retvm_if(result_buf_size == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid result_buf_size");
1181         mm_util_retvm_if((crop_start_x + crop_dest_width > src_width), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid position [%d]]", crop_start_x);
1182         mm_util_retvm_if((crop_start_y + crop_dest_height > src_height), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid position [%d]", crop_start_y);
1183
1184         mm_util_debug("[Input] src[%p] src_width[%u] src_height[%u] src_format[%d] crop_start_x[%u] crop_start_y[%u] crop_dest_width[%u] crop_dest_height[%u]",
1185                                                 src, src_width, src_height, src_format, crop_start_x, crop_start_y, crop_dest_width, crop_dest_height);
1186
1187         __mm_util_get_crop_image_size(src_format, crop_dest_width, crop_dest_height, &dst_buf_size);
1188         mm_util_retvm_if(dst_buf_size == 0, MM_UTIL_ERROR_INVALID_OPERATION, "fail to get dst_buf_size");
1189
1190         dst_buffer = calloc(1, dst_buf_size);
1191         mm_util_retvm_if(dst_buffer == NULL, MM_UTIL_ERROR_OUT_OF_MEMORY, "memory alloc fail");
1192
1193         res_w = crop_dest_width;
1194         res_h = crop_dest_height;
1195
1196         switch (src_format) {
1197         case MM_UTIL_COLOR_RGB24: {
1198                 ret = __mm_util_crop_rgb888(src, src_width, src_height, crop_start_x, crop_start_y, res_w, res_h, dst_buffer);
1199                 break;
1200                 }
1201         case MM_UTIL_COLOR_RGB16: {
1202                 ret = __mm_util_crop_rgb565(src, src_width, src_height, crop_start_x, crop_start_y, res_w, res_h, dst_buffer);
1203                 break;
1204                 }
1205         case MM_UTIL_COLOR_ARGB:
1206         case MM_UTIL_COLOR_BGRA:
1207         case MM_UTIL_COLOR_RGBA:
1208         case MM_UTIL_COLOR_BGRX: {
1209                 ret = __mm_util_crop_rgba32(src, src_width, src_height, crop_start_x, crop_start_y, res_w, res_h, dst_buffer);
1210                 break;
1211                 }
1212         case MM_UTIL_COLOR_I420:
1213         case MM_UTIL_COLOR_YUV420: {
1214                 if ((crop_dest_width % 2) != 0) {
1215                         mm_util_warn("#YUV Width value(%d) must be even at least# ", crop_dest_width);
1216                         res_w = ((crop_dest_width+1)>>1)<<1;
1217                         mm_util_debug("Image isplay is suceeded when YUV crop width value %d", res_w);
1218                 }
1219
1220                 if ((crop_dest_height % 2) != 0) { /* height value must be also even when crop yuv image */
1221                         mm_util_warn("#YUV Height value(%d) must be even at least# ", crop_dest_height);
1222                         res_h = ((crop_dest_height+1)>>1)<<1;
1223                         mm_util_debug("Image isplay is suceeded when YUV crop height value %d", res_h);
1224                 }
1225
1226                 MMUTIL_SAFE_FREE(dst_buffer);
1227                 __mm_util_get_crop_image_size(src_format, res_w, res_h, &dst_buf_size);
1228                 mm_util_retvm_if(dst_buf_size == 0, MM_UTIL_ERROR_INVALID_OPERATION, "fail to get dst_buf_size");
1229
1230                 dst_buffer = calloc(1, dst_buf_size);
1231                 mm_util_retvm_if(dst_buffer == NULL, MM_UTIL_ERROR_OUT_OF_MEMORY, "memory alloc fail");
1232
1233                 ret = __mm_util_crop_yuv420(src, src_width, src_height, crop_start_x, crop_start_y, res_w, res_h, dst_buffer);
1234                 break;
1235                 }
1236         default:
1237                 mm_util_debug("Not supported format");
1238                 MMUTIL_SAFE_FREE(dst_buffer);
1239                 ret = MM_UTIL_ERROR_NOT_SUPPORTED_FORMAT;
1240         }
1241
1242         *result_buf_size = (size_t)dst_buf_size;
1243         *dst = dst_buffer;
1244         *result_buf_width = res_w;
1245         *result_buf_height = res_h;
1246
1247         mm_util_fleave();
1248
1249         return ret;
1250 }
1251
1252 int mm_util_get_image_size(mm_util_color_format_e format, unsigned int width, unsigned int height, size_t *imgsize)
1253 {
1254         int ret = MM_UTIL_ERROR_NONE;
1255         unsigned char x_chroma_shift = 0;
1256         unsigned char y_chroma_shift = 0;
1257         int size, w2, h2, size2;
1258         int stride, stride2;
1259
1260         mm_util_fenter();
1261
1262         mm_util_retvm_if((imgsize == NULL), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid imgsize");
1263         mm_util_retvm_if((IS_MM_UTIL_COLOR_FORMAT(format) == FALSE), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid format [%d]", format);
1264         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");
1265
1266         *imgsize = 0;
1267
1268         switch (format) {
1269         case MM_UTIL_COLOR_I420:
1270         case MM_UTIL_COLOR_YUV420:
1271                 x_chroma_shift = 1;
1272                 y_chroma_shift = 1;
1273                 stride = MM_UTIL_ROUND_UP_4(width);
1274                 h2 = ROUND_UP_X(height, x_chroma_shift);
1275                 size = stride * h2;
1276                 w2 = DIV_ROUND_UP_X(width, x_chroma_shift);
1277                 stride2 = MM_UTIL_ROUND_UP_4(w2);
1278                 h2 = DIV_ROUND_UP_X(height, y_chroma_shift);
1279                 size2 = stride2 * h2;
1280                 *imgsize = size + 2 * size2;
1281                 break;
1282         case MM_UTIL_COLOR_YUV422:
1283         case MM_UTIL_COLOR_YUYV:
1284         case MM_UTIL_COLOR_UYVY:
1285         case MM_UTIL_COLOR_NV16:
1286         case MM_UTIL_COLOR_NV61:
1287                 stride = MM_UTIL_ROUND_UP_4(width) * 2;
1288                 size = stride * height;
1289                 *imgsize = size;
1290                 break;
1291
1292         case MM_UTIL_COLOR_RGB16:
1293                 stride = MM_UTIL_ROUND_UP_4(width) * 2;
1294                 size = stride * height;
1295                 *imgsize = size;
1296                 break;
1297
1298         case MM_UTIL_COLOR_RGB24:
1299                 stride = MM_UTIL_ROUND_UP_4(width) * 3;
1300                 size = stride * height;
1301                 *imgsize = size;
1302                 break;
1303
1304         case MM_UTIL_COLOR_ARGB:
1305         case MM_UTIL_COLOR_BGRA:
1306         case MM_UTIL_COLOR_RGBA:
1307         case MM_UTIL_COLOR_BGRX:
1308                 stride = width * 4;
1309                 size = stride * height;
1310                 *imgsize = size;
1311                 break;
1312
1313         case MM_UTIL_COLOR_NV12:
1314         case MM_UTIL_COLOR_NV12_TILED:
1315         case MM_UTIL_COLOR_NV21:
1316                 x_chroma_shift = 1;
1317                 y_chroma_shift = 1;
1318                 stride = MM_UTIL_ROUND_UP_4(width);
1319                 h2 = ROUND_UP_X(height, y_chroma_shift);
1320                 size = stride * h2;
1321                 w2 = 2 * DIV_ROUND_UP_X(width, x_chroma_shift);
1322                 stride2 = MM_UTIL_ROUND_UP_4(w2);
1323                 h2 = DIV_ROUND_UP_X(height, y_chroma_shift);
1324                 size2 = stride2 * h2;
1325                 *imgsize = size + size2;
1326                 break;
1327
1328         default:
1329                 mm_util_error("Not supported format");
1330                 return MM_UTIL_ERROR_NOT_SUPPORTED_FORMAT;
1331         }
1332
1333         mm_util_debug("format: %u, *imgsize: %u", format, *imgsize);
1334
1335         return ret;
1336 }
1337