Remove mm_util_imgp_h to remove internal handle
[platform/core/api/image-util.git] / src / image_util.c
1 /*
2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <gmodule.h>
18 #include <inttypes.h>
19 #include <mm_util_imgp.h>
20 #include <mm_util_common.h>
21
22 #include <image_util.h>
23 #include <image_util_private.h>
24
25 typedef struct {
26         mm_util_color_format_e image_format;
27         media_format_mimetype_e mimetype;
28         const char *mimetype_name;
29 } image_format_mimetype_pair_s;
30
31 static const image_format_mimetype_pair_s image_format_mimetype_table[MM_UTIL_COLOR_NUM] = {
32         { MM_UTIL_COLOR_YUV420, MEDIA_FORMAT_YV12,              "MEDIA_FORMAT_YV12" },
33         { MM_UTIL_COLOR_YUV422, MEDIA_FORMAT_422P,              "MEDIA_FORMAT_422P" },
34         { MM_UTIL_COLOR_I420,           MEDIA_FORMAT_I420,              "MEDIA_FORMAT_I420" },
35         { MM_UTIL_COLOR_NV12,           MEDIA_FORMAT_NV12,                                              "Not support" },
36         { MM_UTIL_COLOR_UYVY,           MEDIA_FORMAT_UYVY,              "MEDIA_FORMAT_UYVY" },
37         { MM_UTIL_COLOR_YUYV,           MEDIA_FORMAT_YUYV,              "MEDIA_FORMAT_YUYV" },
38         { MM_UTIL_COLOR_RGB16,  MEDIA_FORMAT_RGB565,    "MEDIA_FORMAT_RGB565" },
39         { MM_UTIL_COLOR_RGB24,  MEDIA_FORMAT_RGB888,    "MEDIA_FORMAT_RGB888" },
40         { MM_UTIL_COLOR_ARGB,   MEDIA_FORMAT_ARGB,              "MEDIA_FORMAT_ARGB" },
41         { MM_UTIL_COLOR_BGRA,   MEDIA_FORMAT_BGRA,              "MEDIA_FORMAT_BGRA" },
42         { MM_UTIL_COLOR_RGBA,   MEDIA_FORMAT_RGBA,              "MEDIA_FORMAT_RGBA" },
43         { MM_UTIL_COLOR_BGRX,   -1,                                             "Not support" },
44         { MM_UTIL_COLOR_NV12_TILED,     MEDIA_FORMAT_NV12T,     "MEDIA_FORMAT_NV12T" },
45         { MM_UTIL_COLOR_NV16,           MEDIA_FORMAT_NV16,              "MEDIA_FORMAT_NV16" },
46         { MM_UTIL_COLOR_NV61,           -1,                                             "Not support" }
47 };
48
49 static media_format_mimetype_e __image_format_to_mimetype(mm_util_color_format_e format)
50 {
51         unsigned int i = 0;
52         media_format_mimetype_e mimetype = -1;
53
54         for (i = 0; i < MM_UTIL_COLOR_NUM; i++) {
55                 if (image_format_mimetype_table[i].image_format == format) {
56                         mimetype = image_format_mimetype_table[i].mimetype;
57                         break;
58                 }
59         }
60
61         image_util_debug("imgp fmt: %d mimetype fmt: %s", format, image_format_mimetype_table[i].mimetype_name);
62
63         return mimetype;
64 }
65
66 static mm_util_color_format_e __mimetype_to_image_format(media_format_mimetype_e mimetype)
67 {
68         unsigned int i = 0;
69         mm_util_color_format_e format = -1;
70
71         for (i = 0; i < MM_UTIL_COLOR_NUM; i++) {
72                 if (image_format_mimetype_table[i].mimetype == mimetype) {
73                         format = image_format_mimetype_table[i].image_format;
74                         break;
75                 }
76         }
77
78         image_util_debug("mimetype: %s imgp fmt: %d", image_format_mimetype_table[i].mimetype_name, format);
79
80         return format;
81 }
82
83 static int __create_media_format(media_format_mimetype_e mimetype, unsigned int width, unsigned int height, media_format_h *new_fmt)
84 {
85         int err = MEDIA_FORMAT_ERROR_NONE;
86
87         image_util_retvm_if((new_fmt == NULL) || (width == 0) || (height == 0), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid parameter");
88
89         err = media_format_create(new_fmt);
90         image_util_retvm_if((err != MEDIA_FORMAT_ERROR_NONE), IMAGE_UTIL_ERROR_INVALID_OPERATION, "media_format_make_writable failed (%d)", err);
91
92         err = media_format_set_video_mime(*new_fmt, mimetype);
93         if (err != MEDIA_FORMAT_ERROR_NONE) {
94                 media_format_unref(*new_fmt);
95                 image_util_error("media_format_set_video_mime failed (%d)", err);
96                 return IMAGE_UTIL_ERROR_INVALID_OPERATION;
97         }
98
99         err = media_format_set_video_width(*new_fmt, width);
100         if (err != MEDIA_FORMAT_ERROR_NONE) {
101                 media_format_unref(*new_fmt);
102                 image_util_error("media_format_set_video_width failed (%d)", err);
103                 return IMAGE_UTIL_ERROR_INVALID_OPERATION;
104         }
105
106         err = media_format_set_video_height(*new_fmt, height);
107         if (err != MEDIA_FORMAT_ERROR_NONE) {
108                 media_format_unref(*new_fmt);
109                 image_util_error("media_format_set_video_height failed (%d)", err);
110                 return IMAGE_UTIL_ERROR_INVALID_OPERATION;
111         }
112
113         return IMAGE_UTIL_ERROR_NONE;
114 }
115
116 static void __mm_util_destroy_color_image(mm_image_info_s *image)
117 {
118         if (image == NULL) {
119                 image_util_error("[ERROR] - image");
120                 return;
121         }
122
123         IMAGE_UTIL_SAFE_FREE(image->data);
124         IMAGE_UTIL_SAFE_FREE(image);
125 }
126
127 static int __mm_util_create_color_image(mm_image_info_s **image, unsigned long width, unsigned long height, mm_util_color_format_e color, void *data, size_t size)
128 {
129         int ret = IMAGE_UTIL_ERROR_NONE;
130         mm_image_info_s *_color_image = NULL;
131
132         image_util_retvm_if((image == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid handle");
133         image_util_retvm_if((color >= MM_UTIL_COLOR_NUM), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid color");
134         image_util_retvm_if((data == NULL || size == 0), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid data");
135
136         _color_image = (mm_image_info_s *)calloc(1, sizeof(mm_image_info_s));
137         image_util_retvm_if((_color_image == NULL), IMAGE_UTIL_ERROR_OUT_OF_MEMORY, "Memory allocation failed");
138
139         _color_image->data = calloc(1, size);
140         if (_color_image->data == NULL) {
141                 image_util_error("Memory allocation failed");
142                 __mm_util_destroy_color_image(_color_image);
143                 *image = NULL;
144                 return IMAGE_UTIL_ERROR_OUT_OF_MEMORY;
145         }
146
147         memcpy(_color_image->data, data, size);
148
149         _color_image->size = size;
150         _color_image->width = width;
151         _color_image->height = height;
152         _color_image->color = color;
153
154         image_util_debug("w [%lu], h [%lu], color [%u], size [%zu], data [%p]", _color_image->width, _color_image->height, _color_image->color, _color_image->size, _color_image->data);
155
156         *image = _color_image;
157
158         return ret;
159 }
160
161 static int __mm_util_get_color_image(mm_image_info_s *image, unsigned long *width, unsigned long *height, mm_util_color_format_e *color, void **data, size_t *size)
162 {
163         int ret = IMAGE_UTIL_ERROR_NONE;
164
165         image_util_retvm_if((image == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid handle");
166
167         if (width != NULL)
168                 *width = image->width;
169
170         if (height != NULL)
171                 *height = image->height;
172
173         if (color != NULL)
174                 *color = image->color;
175
176         if (data != NULL)
177                 *data = image->data;
178
179         if (size != NULL)
180                 *size = image->size;
181
182         return ret;
183 }
184
185 static void __mm_destroy_temp_buffer(unsigned char *buffer[])
186 {
187         int i = 0;
188
189         for (i = 0; i < 4; i++)
190                 IMAGE_UTIL_SAFE_FREE(buffer[i]);
191 }
192
193 static int __mm_util_processing(mm_util_s *handle)
194 {
195         int ret = IMAGE_UTIL_ERROR_NONE;
196         unsigned char *dst_buf[4] = {NULL,};
197         unsigned int src_width = 0, src_height = 0;
198         mm_util_color_format_e src_format = -1;
199         unsigned int src_index = 0, dst_index = 0;
200         unsigned int res_w = 0;
201         unsigned int res_h = 0;
202         unsigned char *res_buffer = NULL;
203         unsigned char *res_buffer_conv = NULL;
204         unsigned char *res_buffer_rotate = NULL;
205         size_t res_buffer_size = 0;
206
207         image_util_retvm_if(handle == NULL, IMAGE_UTIL_ERROR_INVALID_PARAMETER, "invalid handle");
208
209         image_util_debug("src: %p, dst: %p", handle->src, handle->dst);
210
211         dst_buf[src_index] = calloc(1, handle->src->size);
212         src_width = handle->src->width;
213         src_height = handle->src->height;
214         src_format = handle->src->color;
215         if (dst_buf[src_index] == NULL) {
216                 image_util_error("[multi func] memory allocation error");
217                 return IMAGE_UTIL_ERROR_INVALID_OPERATION;
218         }
219         memcpy(dst_buf[src_index], handle->src->data, handle->src->size);
220
221         if (handle->set_crop) {
222                 dst_index++;
223
224                 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);
225                 if (ret != MM_UTIL_ERROR_NONE) {
226                         __mm_destroy_temp_buffer(dst_buf);
227                         image_util_error("mm_util_crop_image failed");
228                         return _image_error_capi(ERR_TYPE_TRANSFORM, ret);
229                 }
230
231                 dst_buf[dst_index] = res_buffer;
232                 src_index = dst_index;
233                 src_width = res_w;
234                 src_height = res_h;
235         } else if (handle->set_resize) {
236                 dst_index++;
237
238                 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);
239                 if (ret != MM_UTIL_ERROR_NONE) {
240                         __mm_destroy_temp_buffer(dst_buf);
241                         image_util_error("mm_util_resize_image failed");
242                         return _image_error_capi(ERR_TYPE_TRANSFORM, ret);
243                 }
244
245                 dst_buf[dst_index] = res_buffer;
246                 src_index = dst_index;
247                 src_width = res_w;
248                 src_height = res_h;
249         }
250
251         if (handle->set_convert) {
252                 dst_index++;
253
254                 ret = mm_util_convert_colorspace(dst_buf[src_index], src_width, src_height, src_format, handle->dst_format, &res_buffer_conv, &res_w, &res_h, &res_buffer_size);
255                 if (ret != MM_UTIL_ERROR_NONE) {
256                         __mm_destroy_temp_buffer(dst_buf);
257                         image_util_error("mm_util_convert_colorspace failed");
258                         return _image_error_capi(ERR_TYPE_TRANSFORM, ret);
259                 }
260
261                 dst_buf[dst_index] = res_buffer_conv;
262                 src_index = dst_index;
263                 src_format = handle->dst_format;
264                 src_width = res_w;
265                 src_height = res_h;
266         }
267
268         if (handle->set_rotate) {
269                 dst_index++;
270
271                 ret = mm_util_rotate_image(dst_buf[src_index], src_width, src_height, src_format, handle->rotation, &res_buffer_rotate, &res_w, &res_h, &res_buffer_size);
272                 if (ret != MM_UTIL_ERROR_NONE) {
273                         __mm_destroy_temp_buffer(dst_buf);
274                         image_util_error("mm_util_rotate_image failed");
275                         return _image_error_capi(ERR_TYPE_TRANSFORM, ret);
276                 }
277
278                 dst_buf[dst_index] = res_buffer_rotate;
279                 src_index = dst_index;
280                 src_width = res_w;
281                 src_height = res_h;
282         }
283
284         if (dst_buf[dst_index] != NULL && res_buffer_size != 0) {
285                 ret = __mm_util_create_color_image(&(handle->dst), (unsigned long)src_width, (unsigned long)src_height, src_format, (void *)dst_buf[dst_index], res_buffer_size);
286                 if (ret != IMAGE_UTIL_ERROR_NONE)
287                         image_util_error("__mm_util_create_color_image failed");
288         } else {
289                 image_util_error("invalid result %p %zu", dst_buf[dst_index], res_buffer_size);
290                 ret = IMAGE_UTIL_ERROR_INVALID_OPERATION;
291         }
292         __mm_destroy_temp_buffer(dst_buf);
293
294         image_util_error("mm_util_processing was finished");
295
296         return ret;
297 }
298
299 static int __mm_util_transform_exec(mm_util_s *handle, mm_image_info_s *source_image)
300 {
301         int ret = IMAGE_UTIL_ERROR_NONE;
302
303         image_util_retvm_if(handle == NULL, IMAGE_UTIL_ERROR_INVALID_PARAMETER, "invalid handle");
304         image_util_retvm_if(source_image == NULL, IMAGE_UTIL_ERROR_INVALID_PARAMETER, "invalid source_image");
305
306         image_util_debug("orig_image: %p [%zu] %lu X %lu (%u)", source_image->data, source_image->size, source_image->width, source_image->height, source_image->color);
307
308         handle->src = source_image;
309         handle->dst = NULL;
310
311         ret = __mm_util_processing(handle);
312         image_util_retvm_if(ret != IMAGE_UTIL_ERROR_NONE, ret, "__mm_util_processing failed [%d]", ret);
313
314         image_util_debug("result_image: %p [%zu] %lu X %lu (%u)", handle->dst->data, handle->dst->size, handle->dst->width, handle->dst->height, handle->dst->color);
315
316         return ret;
317 }
318
319 static int __image_util_image_to_packet(mm_image_info_s *image, media_packet_h *packet)
320 {
321         int err = IMAGE_UTIL_ERROR_NONE;
322         mm_util_color_format_e format = 0;
323         unsigned long width = 0, height = 0;
324         void *buffer = NULL;
325         size_t buffer_size = 0;
326         media_format_h fmt = NULL;
327         void *packet_ptr = NULL;
328         uint64_t packet_size = 0;
329         size_t size = 0;
330
331         image_util_fenter();
332
333         err = __mm_util_get_color_image(image, &width, &height, &format, &buffer, &buffer_size);
334         image_util_retvm_if((err != IMAGE_UTIL_ERROR_NONE), err, "__mm_util_get_color_image failed (%d)", err);
335
336         err = __create_media_format(__image_format_to_mimetype(format), (unsigned int)width, (unsigned int)height, &fmt);
337         image_util_retvm_if((err != IMAGE_UTIL_ERROR_NONE), err, "__create_media_format failed (%d)", err);
338
339         err = media_packet_create_alloc(fmt, NULL, NULL, packet);
340         if (err != MEDIA_PACKET_ERROR_NONE) {
341                 image_util_error("media_packet_create_alloc failed (%d)", err);
342                 media_format_unref(fmt);
343                 return IMAGE_UTIL_ERROR_INVALID_OPERATION;
344         }
345
346         err = media_packet_get_buffer_size(*packet, &packet_size);
347         if (err != MEDIA_PACKET_ERROR_NONE) {
348                 image_util_error("media_packet_get_buffer_size failed (%d)", err);
349                 media_packet_destroy(*packet);
350                 return IMAGE_UTIL_ERROR_INVALID_OPERATION;
351         }
352
353         err = media_packet_get_buffer_data_ptr(*packet, &packet_ptr);
354         if (err != MEDIA_PACKET_ERROR_NONE) {
355                 image_util_error("media_packet_get_buffer_data_ptr failed");
356                 media_packet_destroy(*packet);
357                 return IMAGE_UTIL_ERROR_INVALID_OPERATION;
358         }
359
360         if (packet_ptr == NULL || packet_size == 0) {
361                 image_util_error("media_packet creation failed (%p, %" PRIu64 ")", packet_ptr, packet_size);
362                 media_packet_destroy(*packet);
363                 return IMAGE_UTIL_ERROR_INVALID_OPERATION;
364         }
365         image_util_debug("Success - media_packet is created (%p, %" PRIu64 ")", packet_ptr, packet_size);
366
367         if ((uint64_t)buffer_size < packet_size) {
368                 size = (size_t)buffer_size;
369         } else {
370                 size = (size_t)packet_size;
371         }
372
373         image_util_debug("Size: result(%u) media_packet(%" PRIu64 ") copied(%zu)", buffer_size, packet_size, size);
374         memcpy(packet_ptr, buffer, size);
375
376         err = media_packet_set_buffer_size(*packet, (uint64_t)size);
377         if (err != MEDIA_PACKET_ERROR_NONE) {
378                 image_util_error("media_packet_set_buffer_size failed (%d)", err);
379                 media_packet_destroy(*packet);
380                 return IMAGE_UTIL_ERROR_INVALID_OPERATION;
381         }
382
383         image_util_fleave();
384
385         return IMAGE_UTIL_ERROR_NONE;
386 }
387
388 gpointer __mm_util_thread_repeate(gpointer data)
389 {
390         mm_util_s *handle = (mm_util_s *) data;
391         int ret = IMAGE_UTIL_ERROR_NONE;
392         mm_image_info_s *pop_data = NULL;
393         media_packet_h packet = NULL;
394
395         image_util_retvm_if(handle == NULL, NULL, "invalid handle");
396
397         while (!handle->is_finish) {
398                 image_util_debug("waiting...");
399                 pop_data = g_async_queue_timeout_pop(handle->queue, 300 * G_TIME_SPAN_MILLISECOND);
400                 image_util_debug("get from data or timeout");
401
402                 if (pop_data == NULL) {
403                         image_util_error("The data is null");
404                         continue;
405                 }
406
407                 ret = __mm_util_transform_exec(handle, (mm_image_info_s *)pop_data); /* Need to block */
408                 if (ret == IMAGE_UTIL_ERROR_NONE)
409                         image_util_debug("Success - transform_exec");
410                 else
411                         image_util_error("Error - transform_exec");
412
413                 if ((handle->_util_cb != NULL) && (handle->_util_cb->completed_cb != NULL)) {
414                         image_util_debug("completed_cb is called");
415                         ret = __image_util_image_to_packet(handle->dst, &packet);
416                         if (ret != IMAGE_UTIL_ERROR_NONE) {
417                                 image_util_error("__image_util_image_to_packet failed (%d)", ret);
418                                 handle->_util_cb->completed_cb(NULL, ret, handle->_util_cb->user_data);
419                         } else {
420                                 handle->_util_cb->completed_cb(&packet, ret, handle->_util_cb->user_data);
421                         }
422                 } else {
423                         image_util_error("There is no callback");
424                 }
425                 __mm_util_destroy_color_image(pop_data);
426                 __mm_util_destroy_color_image(handle->dst);
427                 handle->is_completed = FALSE;
428         }
429
430         image_util_debug("exit thread");
431         handle->thread = NULL;
432
433         return NULL;
434 }
435
436 static int __mm_util_create_thread(mm_util_s *handle)
437 {
438         int ret = IMAGE_UTIL_ERROR_NONE;
439
440         image_util_retvm_if(handle == NULL, IMAGE_UTIL_ERROR_INVALID_PARAMETER, "invalid handle");
441         image_util_retvm_if(handle->thread != NULL, IMAGE_UTIL_ERROR_NONE, "[NO-ERROR] Thread is already created");
442
443         /*create threads*/
444         handle->thread = g_thread_new("transform_thread", (GThreadFunc)__mm_util_thread_repeate, (gpointer)handle);
445         image_util_retvm_if(handle->thread == NULL, IMAGE_UTIL_ERROR_INVALID_OPERATION, "ERROR - create thread");
446
447         image_util_debug("New thread is created");
448
449         return ret;
450 }
451
452 static int __mm_util_transform(mm_util_s *handle, mm_image_info_s *image)
453 {
454         int ret = IMAGE_UTIL_ERROR_NONE;
455
456         image_util_fenter();
457
458         image_util_retvm_if(handle == NULL, IMAGE_UTIL_ERROR_INVALID_PARAMETER, "invalid handle");
459         image_util_retvm_if(image == NULL, IMAGE_UTIL_ERROR_INVALID_PARAMETER, "invalid image");
460
461         image_util_debug("image: %p", image);
462
463         if (handle->queue) {
464                 image_util_debug("g_async_queue_push");
465                 g_async_queue_push(handle->queue, GINT_TO_POINTER(image));
466                 ret = __mm_util_create_thread(handle);
467                 if (ret != IMAGE_UTIL_ERROR_NONE) {
468                         image_util_error("ERROR - Create thread");
469                         return ret;
470                 } else {
471                         image_util_debug("Success -__mm_util_create_thread");
472                 }
473         }
474
475         image_util_fleave();
476
477         return ret;
478 }
479
480 static int _image_util_packet_to_image(media_packet_h packet, mm_image_info_s **color_image)
481 {
482         int err = IMAGE_UTIL_ERROR_NONE;
483         media_format_mimetype_e mimetype = 0;
484         int width = 0, height = 0;
485         uint64_t size = 0;
486         void *ptr = NULL;
487         media_format_h fmt = NULL;
488
489         image_util_retvm_if(((packet == NULL) || (color_image == NULL)), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid parameter");
490
491         err = media_packet_get_format(packet, &fmt);
492         image_util_retvm_if((err != MEDIA_PACKET_ERROR_NONE), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "media_packet_get_format failed (%d)", err);
493
494         err = media_format_get_video_info(fmt, &mimetype, &width, &height, NULL, NULL);
495         if (err != MEDIA_FORMAT_ERROR_NONE) {
496                 image_util_error("media_packet_get_format failed (%d)", err);
497                 media_format_unref(fmt);
498                 return IMAGE_UTIL_ERROR_INVALID_PARAMETER;
499         }
500         media_format_unref(fmt);
501
502         err = media_packet_get_buffer_size(packet, &size);
503         image_util_retvm_if((err != MEDIA_PACKET_ERROR_NONE), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "media_packet_get_buffer_size failed (%d)", err);
504
505         if (size) {
506                 err = media_packet_get_buffer_data_ptr(packet, &ptr);
507                 image_util_retvm_if((err != MEDIA_PACKET_ERROR_NONE), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "media_packet_get_buffer_data_ptr failed (%d)", err);
508         }
509
510         image_util_debug("[Fotmat: %u] W x H : %d x %d", mimetype, width, height);
511         image_util_retvm_if(((width == 0) || (height == 0) || (size == 0) || (ptr == NULL)), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid source packet");
512
513         err = __mm_util_create_color_image(color_image, (unsigned long)width, (unsigned long)height, __mimetype_to_image_format(mimetype), ptr, (size_t)size);
514         image_util_retvm_if((err != IMAGE_UTIL_ERROR_NONE), err, "__mm_util_create_color_image failed (%d)", err);
515
516         image_util_debug("_image_util_packet_to_image succeed");
517
518         return IMAGE_UTIL_ERROR_NONE;
519 }
520
521 static int _image_util_create_transform_handle(transformation_s *handle)
522 {
523         int ret = IMAGE_UTIL_ERROR_NONE;
524         mm_util_s *_handle = NULL;
525
526         image_util_retvm_if((handle == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "invalid handle");
527
528         _handle = calloc(1, sizeof(mm_util_s));
529         image_util_retvm_if((_handle == NULL), IMAGE_UTIL_ERROR_OUT_OF_MEMORY, "OUT_OF_MEMORY");
530
531         /* private values init */
532         _handle->dst = NULL;
533         _handle->dst_format = MM_UTIL_COLOR_NUM;
534         _handle->rotation = MM_UTIL_ROTATE_0;
535
536         _handle->start_x = -1;
537         _handle->start_y = -1;
538         _handle->dst_width = 0;
539         _handle->dst_height = 0;
540         _handle->is_completed = FALSE;
541         _handle->is_finish = FALSE;
542
543         _handle->set_convert = FALSE;
544         _handle->set_crop = FALSE;
545         _handle->set_resize = FALSE;
546         _handle->set_rotate = FALSE;
547
548         /*These are a communicator for thread*/
549         if (!_handle->queue)
550                 _handle->queue = g_async_queue_new();
551
552         if (_handle->queue == NULL) {
553                 image_util_error("g_async_queue_new failed");
554                 IMAGE_UTIL_SAFE_FREE(_handle);
555                 return IMAGE_UTIL_ERROR_INVALID_OPERATION;
556         }
557
558         handle->image_h = _handle;
559
560         return ret;
561 }
562
563 int image_util_transform_create(transformation_h * handle)
564 {
565         int err = IMAGE_UTIL_ERROR_NONE;
566
567         image_util_fenter();
568
569         image_util_retvm_if((handle == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid Handle");
570
571         transformation_s *_handle = (transformation_s *) calloc(1, sizeof(transformation_s));
572         image_util_retvm_if((_handle == NULL), IMAGE_UTIL_ERROR_OUT_OF_MEMORY, "OUT_OF_MEMORY");
573
574         _handle->image_h = NULL;
575
576         err = _image_util_create_transform_handle(_handle);
577         if (err != IMAGE_UTIL_ERROR_NONE) {
578                 image_util_error("Error - create transform handle");
579                 IMAGE_UTIL_SAFE_FREE(_handle);
580                 return IMAGE_UTIL_ERROR_INVALID_OPERATION;
581         }
582
583         *handle = (transformation_h) _handle;
584
585         return IMAGE_UTIL_ERROR_NONE;
586 }
587
588 int image_util_transform_set_hardware_acceleration(transformation_h handle, bool mode)
589 {
590         transformation_s *_handle = (transformation_s *) handle;
591
592         image_util_warning("DEPRECATION WARNING: image_util_transform_set_hardware_acceleration() is deprecated and will be removed from next release.");
593         image_util_debug("Set hardware_acceleration %d", mode);
594
595         image_util_retvm_if((_handle == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid Handle");
596 #ifndef ENABLE_HW_ACCELERATION
597         image_util_retvm_if((mode == true), IMAGE_UTIL_ERROR_NOT_SUPPORTED, "hardware acceleration is not supported");
598 #endif
599
600         image_util_debug("Set hardware_acceleration %d", mode);
601
602         return IMAGE_UTIL_ERROR_NONE;
603 }
604
605 int image_util_transform_set_colorspace(transformation_h handle, image_util_colorspace_e colorspace)
606 {
607         transformation_s *_handle = (transformation_s *) handle;
608
609         image_util_debug("Set colorspace_convert_info [%d]", colorspace);
610
611         image_util_retvm_if((_handle == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid Handle");
612         image_util_retvm_if((_handle->image_h == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid Image Handle");
613
614         _handle->image_h->dst_format = colorspace;
615         _handle->image_h->set_convert = true;
616
617         return IMAGE_UTIL_ERROR_NONE;
618 }
619
620 int image_util_transform_set_resolution(transformation_h handle, unsigned int width, unsigned int height)
621 {
622         transformation_s *_handle = (transformation_s *) handle;
623
624         image_util_debug("Set resize_info w[%d] h[%d]", width, height);
625
626         image_util_retvm_if((_handle == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid Handle");
627         image_util_retvm_if((_handle->image_h == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid Image Handle");
628         image_util_retvm_if((_handle->image_h->set_crop), IMAGE_UTIL_ERROR_INVALID_OPERATION, "Crop and Resize can't do at the same time");
629         image_util_retvm_if((_image_util_check_resolution(width, height) == false), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid resolution");
630
631         _handle->image_h->dst_width = width;
632         _handle->image_h->dst_height = height;
633         _handle->image_h->set_resize = true;
634
635         return IMAGE_UTIL_ERROR_NONE;
636 }
637
638 int image_util_transform_set_rotation(transformation_h handle, image_util_rotation_e rotation)
639 {
640         transformation_s *_handle = (transformation_s *) handle;
641
642         image_util_debug("Set rotate_info [%d]", rotation);
643
644         image_util_retvm_if((_handle == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid Handle");
645         image_util_retvm_if((_handle->image_h == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid Image Handle");
646
647         _handle->image_h->rotation = rotation;
648         _handle->image_h->set_rotate = true;
649
650         return IMAGE_UTIL_ERROR_NONE;
651 }
652
653 int image_util_transform_set_crop_area(transformation_h handle, unsigned int start_x, unsigned int start_y, unsigned int end_x, unsigned int end_y)
654 {
655         transformation_s *_handle = (transformation_s *) handle;
656         int dest_width = 0;
657         int dest_height = 0;
658
659         image_util_retvm_if((_handle == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid Handle");
660         image_util_retvm_if((_handle->image_h == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid Image Handle");
661         image_util_retvm_if((_handle->image_h->set_resize), IMAGE_UTIL_ERROR_INVALID_OPERATION, "Crop and Resize can't do at the same time");
662
663         dest_width = end_x - start_x;
664         dest_height = end_y - start_y;
665
666         image_util_debug("Set crop_info x[%d] y[%d] w[%d] h[%d]", start_x, start_y, dest_width, dest_height);
667
668         image_util_retvm_if((_image_util_check_resolution(dest_width, dest_height) == false), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid dest resolution");
669
670         _handle->image_h->start_x = start_x;
671         _handle->image_h->start_y = start_y;
672         _handle->image_h->dst_width = dest_width;
673         _handle->image_h->dst_height = dest_height;
674         _handle->image_h->set_crop = true;
675
676         return IMAGE_UTIL_ERROR_NONE;
677 }
678
679 int image_util_transform_get_colorspace(transformation_h handle, image_util_colorspace_e * colorspace)
680 {
681         transformation_s *_handle = (transformation_s *) handle;
682
683         image_util_retvm_if((_handle == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid Handle");
684         image_util_retvm_if((_handle->image_h == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid Image Handle");
685         image_util_retvm_if((colorspace == NULL), IMAGE_UTIL_ERROR_INVALID_OPERATION, "colorspace parameter error");
686         image_util_retvm_if((!_handle->image_h->set_convert), IMAGE_UTIL_ERROR_INVALID_OPERATION, "Did not set colorspace before");
687
688         image_util_debug("Get colorspace_convert_info [%d]", _handle->image_h->dst_format);
689
690         *colorspace = _handle->image_h->dst_format;
691
692         return IMAGE_UTIL_ERROR_NONE;
693 }
694
695 int image_util_transform_get_resolution(transformation_h handle, unsigned int *width, unsigned int *height)
696 {
697         transformation_s *_handle = (transformation_s *) handle;
698
699         image_util_retvm_if((_handle == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid Handle");
700         image_util_retvm_if((_handle->image_h == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid Image Handle");
701         image_util_retvm_if((width == NULL || height == NULL), IMAGE_UTIL_ERROR_INVALID_OPERATION, "width or height parameter error");
702         image_util_retvm_if((!_handle->image_h->set_resize), IMAGE_UTIL_ERROR_INVALID_OPERATION, "Did not set resolution before");
703
704         image_util_debug("Get resize_info w[%ui] h[%ui]", _handle->image_h->dst_width, _handle->image_h->dst_height);
705
706         *width = _handle->image_h->dst_width;
707         *height = _handle->image_h->dst_height;
708
709         return IMAGE_UTIL_ERROR_NONE;
710 }
711
712 int image_util_transform_get_rotation(transformation_h handle, image_util_rotation_e * rotation)
713 {
714         transformation_s *_handle = (transformation_s *) handle;
715
716         image_util_retvm_if((_handle == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid Handle");
717         image_util_retvm_if((_handle->image_h == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid Image Handle");
718         image_util_retvm_if((rotation == NULL), IMAGE_UTIL_ERROR_INVALID_OPERATION, "rotation parameter error");
719         image_util_retvm_if((!_handle->image_h->set_rotate), IMAGE_UTIL_ERROR_INVALID_OPERATION, "Did not set rotation before");
720
721         image_util_debug("Get rotate_info [%d]", _handle->image_h->rotation);
722
723         *rotation = _handle->image_h->rotation;
724
725         return IMAGE_UTIL_ERROR_NONE;
726 }
727
728 int image_util_transform_get_crop_area(transformation_h handle, unsigned int *start_x, unsigned int *start_y, unsigned int *end_x, unsigned int *end_y)
729 {
730         transformation_s *_handle = (transformation_s *) handle;
731
732         image_util_retvm_if((_handle == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid Handle");
733         image_util_retvm_if((_handle->image_h == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid Image Handle");
734         image_util_retvm_if((start_x == NULL || start_y == NULL || end_x == NULL || end_y == NULL), IMAGE_UTIL_ERROR_INVALID_OPERATION, "crop area parameter error");
735         image_util_retvm_if((!_handle->image_h->set_crop), IMAGE_UTIL_ERROR_INVALID_OPERATION, "Did not set crop area before");
736
737         *start_x = _handle->image_h->start_x;
738         *start_y = _handle->image_h->start_y;
739         *end_x = _handle->image_h->start_x + _handle->image_h->dst_width;
740         *end_y = _handle->image_h->start_x + _handle->image_h->dst_height;
741
742         return IMAGE_UTIL_ERROR_NONE;
743 }
744
745 int image_util_transform_run(transformation_h handle, media_packet_h src, image_util_transform_completed_cb completed_cb, void *user_data)
746 {
747         int err = IMAGE_UTIL_ERROR_NONE;
748         transformation_s *_handle = (transformation_s *) handle;
749         mm_image_info_s *color_image = NULL;
750
751         image_util_fenter();
752
753         image_util_retvm_if((_handle == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid Handle");
754         image_util_retvm_if((_handle->image_h == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid Image Handle");
755         image_util_retvm_if((completed_cb == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid callback");
756         image_util_retvm_if((src == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid source");
757         image_util_retvm_if((!_handle->image_h->set_convert && !_handle->image_h->set_resize && !_handle->image_h->set_rotate && !_handle->image_h->set_crop), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid transform");
758
759         err = _image_util_packet_to_image(src, &color_image);
760         image_util_retvm_if((err != IMAGE_UTIL_ERROR_NONE), err, "_image_util_packet_to_image failed");
761
762         _handle->image_h->_util_cb = (image_util_cb_s *) calloc(1, sizeof(image_util_cb_s));
763         if (_handle->image_h->_util_cb == NULL) {
764                 image_util_error("Memory allocation failed");
765                 __mm_util_destroy_color_image(color_image);
766                 return IMAGE_UTIL_ERROR_OUT_OF_MEMORY;
767         }
768
769         _handle->image_h->_util_cb->user_data = user_data;
770         _handle->image_h->_util_cb->completed_cb = completed_cb;
771
772         err = __mm_util_transform(_handle->image_h, color_image);
773         if (err != IMAGE_UTIL_ERROR_NONE) {
774                 image_util_error("Error - Run transform (%d)", err);
775                 __mm_util_destroy_color_image(color_image);
776                 return err;
777         }
778
779         return IMAGE_UTIL_ERROR_NONE;
780 }
781
782 int image_util_transform_destroy(transformation_h handle)
783 {
784         transformation_s *_handle = (transformation_s *) handle;
785
786         image_util_fenter();
787
788         image_util_retvm_if((_handle == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid Handle");
789         image_util_retvm_if((_handle->image_h == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid Image Handle");
790
791         if (_handle->image_h->thread) {
792                 _handle->image_h->is_finish = TRUE;
793                 g_thread_join(_handle->image_h->thread);
794         }
795
796         if (_handle->image_h->queue) {
797                 g_async_queue_unref(_handle->image_h->queue);
798                 _handle->image_h->queue = NULL;
799         }
800
801         IMAGE_UTIL_SAFE_FREE(_handle->image_h->_util_cb);
802         IMAGE_UTIL_SAFE_FREE(_handle->image_h);
803
804         IMAGE_UTIL_SAFE_FREE(_handle);
805
806         image_util_fleave();
807
808         return IMAGE_UTIL_ERROR_NONE;
809 }
810
811 int image_util_calculate_buffer_size(int width, int height, image_util_colorspace_e colorspace, unsigned int *size)
812 {
813         int err = IMAGE_UTIL_ERROR_NONE;
814         size_t size_ptr = 0;
815
816         image_util_retvm_if((is_valid_colorspace(colorspace) == FALSE), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid colorspace");
817         image_util_retvm_if((width <= 0 || height <= 0), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid width or Invalid height");
818         image_util_retvm_if((size == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "size is null");
819
820         err = mm_util_get_image_size(TYPECAST_COLOR(colorspace), width, height, &size_ptr);
821
822         *size = (unsigned int)size_ptr;
823
824         return _image_error_capi(ERR_TYPE_COMMON, err);
825 }
826
827 int image_util_extract_color_from_memory(const unsigned char *image_buffer, int width, int height, unsigned char *rgb_r, unsigned char *rgb_g, unsigned char *rgb_b)
828 {
829         int ret = IMAGE_UTIL_ERROR_NONE;
830
831         image_util_retvm_if((image_buffer == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "image_buffer is null");
832
833         GModule *module = NULL;
834         ModuleFunc mmutil_imgcv_module_func = NULL;
835         module = g_module_open(PATH_MMUTIL_IMGCV_LIB, G_MODULE_BIND_LAZY);
836         image_util_retvm_if((module == NULL), IMAGE_UTIL_ERROR_NO_SUCH_FILE, "fail to open module");
837
838         if (!g_module_symbol(module, IMGCV_FUNC_NAME, (gpointer *)&mmutil_imgcv_module_func)) {
839                 image_util_error("fail to g_module_symbol");
840                 g_module_close(module);
841
842                 return IMAGE_UTIL_ERROR_INVALID_OPERATION;
843         }
844
845         if (!mmutil_imgcv_module_func)
846                 g_module_close(module);
847
848         image_util_retvm_if((mmutil_imgcv_module_func == NULL), IMAGE_UTIL_ERROR_INVALID_OPERATION, "fail to get symbol");
849
850         unsigned char r_color, g_color, b_color;
851         ret = mmutil_imgcv_module_func((void *)image_buffer, width, height, &r_color, &g_color, &b_color);
852
853         *rgb_r = r_color;
854         *rgb_g = g_color;
855         *rgb_b = b_color;
856
857         if (module) {
858                 g_module_close(module);
859                 module = NULL;
860         }
861
862         return _image_error_capi(ERR_TYPE_COMMON, ret);
863 }
864
865 int image_util_foreach_supported_colorspace(image_util_type_e image_type, image_util_supported_colorspace_cb callback, void *user_data)
866 {
867         int idx = 0;
868
869         IMAGE_UTIL_TYPE_CHECK(image_type);
870         image_util_retvm_if((callback == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "callback is null");
871
872         for (idx = (int)(NUM_OF_COLORSPACE - 1); idx >= 0; idx--) {
873                 if (is_supported_colorspace(idx, image_type))
874                         if (false == callback(idx, user_data))
875                                 return IMAGE_UTIL_ERROR_NONE;
876
877         }
878
879         return IMAGE_UTIL_ERROR_NONE;
880 }