Performance enhancement to make image/video thumbnail
[platform/core/multimedia/libmedia-thumbnail.git] / src / media-thumb-internal.c
1 /*
2  * libmedia-thumbnail
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Hyunjun Ko <zzoon.ko@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 "media-thumb-debug.h"
23 #include "media-thumb-util.h"
24 #include "media-thumb-internal.h"
25 #include "media-thumb-ipc.h"
26
27 #include "AGifFrameInfo.h"
28 #include "IfegDecodeAGIF.h"
29 #include "img-codec.h"
30 #include "img-codec-agif.h"
31 #include "img-codec-common.h"
32 #include "img-codec-osal.h"
33 #include "img-codec-parser.h"
34
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <fcntl.h>
38 #include <unistd.h>
39
40 #include <mm_file.h>
41 #include <mm_util_imgp.h>
42 #include <mm_util_jpeg.h>
43 #include <Evas.h>
44 #include <Ecore_Evas.h>
45 #include <libexif/exif-data.h>
46 #include <sys/stat.h>
47 #include <grp.h>
48 #include <pwd.h>
49
50 #define MEDIA_THUMB_ROUND_UP_8(num) (((num)+7)&~7)
51 /* performance enhanced to make thumbnail */
52 #define THUMB_PERFORMANCE_ENHANCED 1
53
54 int _media_thumb_resize_data(unsigned char *src_data,
55                                                         int src_width,
56                                                         int src_height,
57                                                         mm_util_img_format src_format,
58                                                         media_thumb_info *thumb_info,
59                                                         int dst_width,
60                                                         int dst_height);
61
62 int _media_thumb_get_proper_thumb_size(int orig_w, int orig_h,
63                                                                 int *thumb_w, int *thumb_h)
64 {
65         BOOL portrait = FALSE;
66         double ratio;
67
68         if (orig_w < orig_h) {
69                 portrait = TRUE;
70         }
71
72         /* Set smaller length to default size */
73         if (portrait) {
74                 if (orig_w < *thumb_w)
75                         *thumb_w = orig_w;
76                 ratio = (double)orig_h / (double)orig_w;
77                 *thumb_h = *thumb_w * ratio;
78         } else {
79                 if (orig_h < *thumb_h)
80                         *thumb_h = orig_h;
81                 ratio = (double)orig_w / (double)orig_h;
82                 *thumb_w = *thumb_h * ratio;
83         }
84
85         /** CAUTION :: The width of RGB888 raw data has to be rounded by 8 **/
86         *thumb_w = MEDIA_THUMB_ROUND_UP_8(*thumb_w);
87
88         thumb_dbg("proper thumb w: %d h: %d", *thumb_w, *thumb_h);
89
90         return MS_MEDIA_ERR_NONE;
91 }
92
93 int _media_thumb_get_exif_info(ExifData *ed, char *buf, int max_size, int *value, int ifdtype, long tagtype)
94 {
95         ExifEntry *entry;
96         ExifIfd ifd;
97         ExifTag tag;
98
99         if (ed == NULL) {
100                 return MS_MEDIA_ERR_INVALID_PARAMETER;
101         }
102
103         ifd = ifdtype;
104         tag = tagtype;
105
106         entry = exif_content_get_entry(ed->ifd[ifd], tag);
107         if (entry) {
108                 if (tag == EXIF_TAG_ORIENTATION ||
109                                 tag == EXIF_TAG_PIXEL_X_DIMENSION ||
110                                 tag == EXIF_TAG_PIXEL_Y_DIMENSION) {
111
112                         if (value == NULL) {
113                                 thumb_err("value is NULL");
114                                 return MS_MEDIA_ERR_INVALID_PARAMETER;
115                         }
116
117                         ExifByteOrder mByteOrder = exif_data_get_byte_order(ed);
118                         short exif_value = exif_get_short(entry->data, mByteOrder);
119                         *value = (int)exif_value;
120                 } else {
121                         /* Get the contents of the tag in human-readable form */
122                         if (buf == NULL) {
123                                 thumb_err("buf is NULL");
124                                 return MS_MEDIA_ERR_INVALID_PARAMETER;
125                         }
126                         exif_entry_get_value(entry, buf, max_size);
127                         buf[strlen(buf)] = '\0';
128                 }
129         }
130
131         return MS_MEDIA_ERR_NONE;
132 }
133
134 static int _media_thumb_get_data_from_exif(ExifData *ed,
135                                                                                                 void **thumb_data,
136                                                                                                 int *thumb_size,
137                                                                                                 int *thumb_width,
138                                                                                                 int *thumb_height,
139                                                                                                 int *origin_width,
140                                                                                                 int *origin_height)
141 {
142         ExifEntry *entry;
143         ExifIfd ifd;
144         ExifTag tag;
145
146         ExifByteOrder byte_order = exif_data_get_byte_order(ed);
147
148         ifd = EXIF_IFD_1;
149         tag = EXIF_TAG_COMPRESSION;
150
151         entry = exif_content_get_entry(ed->ifd[ifd], tag);
152
153         if (entry) {
154                 /* Get the contents of the tag in human-readable form */
155                 ExifShort value = exif_get_short(entry->data, byte_order);
156                 //thumb_dbg("%s: %d", exif_tag_get_name_in_ifd(tag,ifd), value);
157
158                 if (value == 6) {
159                         thumb_dbg("There's jpeg thumb in this image");
160                 } else {
161                         thumb_dbg("There's NO jpeg thumb in this image");
162                         return MS_MEDIA_ERR_INVALID_PARAMETER;
163                 }
164         } else {
165                 thumb_dbg("entry is NULL");
166                 return MS_MEDIA_ERR_INVALID_PARAMETER;
167         }
168
169         /* copy the real thumbnail data from exif data */
170         if (ed->data && ed->size) {
171                 //thumb_dbg("Size: %d, thumb: 0x%x", ed->size, ed->data);
172                 *thumb_data = (char *)malloc(ed->size);
173
174                 if (*thumb_data == NULL) {
175                         thumb_dbg("malloc failed!");
176                         return MS_MEDIA_ERR_INVALID_PARAMETER;
177                 }
178
179                 memcpy(*thumb_data, (void *)ed->data, ed->size);
180                 *thumb_size = ed->size;
181         } else {
182                 thumb_dbg("data is NULL");
183                 return MS_MEDIA_ERR_INVALID_PARAMETER;
184         }
185
186         /* Get width and height of thumbnail */
187         tag = EXIF_TAG_IMAGE_WIDTH;
188         entry = exif_content_get_entry(ed->ifd[ifd], tag);
189
190         if (entry) {
191                 /* Get the contents of the tag in human-readable form */
192                 char width[10] = {0,};
193                 exif_entry_get_value(entry, width, 10);
194
195                 *thumb_width = atoi(width);
196         } else {
197                 thumb_warn("EXIF_TAG_IMAGE_WIDTH does not exist");
198                 *thumb_width = 0;
199         }
200
201         tag = EXIF_TAG_IMAGE_LENGTH;
202         entry = exif_content_get_entry(ed->ifd[ifd], tag);
203         if (entry) {
204                 /* Get the contents of the tag in human-readable form */
205                 char height[10] = {0, };
206                 exif_entry_get_value(entry, height, 10);
207
208                 *thumb_height = atoi(height);
209         } else {
210                 thumb_warn("EXIF_TAG_IMAGE_LENGTH does not exist");
211                 *thumb_height = 0;
212         }
213
214         thumb_dbg("thumb width : height [%d:%d]", *thumb_width, *thumb_height);
215
216         /* Get width and height of original image from exif */
217         ifd = EXIF_IFD_EXIF;
218         tag = EXIF_TAG_PIXEL_X_DIMENSION;
219         entry = exif_content_get_entry(ed->ifd[ifd], tag);
220
221         if (entry) {
222                 char width[10] = {0,};
223                 exif_entry_get_value(entry, width, 10);
224
225                 *origin_width = atoi(width);
226         } else {
227                 thumb_warn("EXIF_TAG_PIXEL_X_DIMENSION does not exist");
228                 *origin_width = 0;
229         }
230
231         tag = EXIF_TAG_PIXEL_Y_DIMENSION;
232         entry = exif_content_get_entry(ed->ifd[ifd], tag);
233
234         if (entry) {
235                 char height[10] = {0, };
236                 exif_entry_get_value(entry, height, 10);
237
238                 *origin_height = atoi(height);
239         } else {
240                 thumb_warn("EXIF_TAG_PIXEL_Y_DIMENSION does not exist");
241                 *origin_height = 0;
242         }
243
244         return MS_MEDIA_ERR_NONE;
245 }
246
247 int _media_thumb_get_thumb_from_exif(ExifData *ed,
248                                                                 const char *file_full_path,
249                                                                 const char *thumb_path,
250                                                                 int orientation,
251                                                                 int required_width,
252                                                                 int required_height,
253                                                                 media_thumb_info *thumb_info)
254 {
255         int err = MS_MEDIA_ERR_NONE;
256         int size = 0;
257         int thumb_width = 0;
258         int thumb_height = 0;
259         int origin_width = 0;
260         int origin_height = 0;
261         void *thumb = NULL;
262         bool is_rotated = (orientation == ROT_90 || orientation == ROT_180 || orientation == ROT_270) ? TRUE : FALSE;
263         mm_util_jpeg_yuv_data decoded = {0,};
264
265         if (ed == NULL) {
266                 return MS_MEDIA_ERR_INVALID_PARAMETER;
267         }
268
269         err = _media_thumb_get_data_from_exif(ed,
270                                                                                 &thumb,
271                                                                                 &size,
272                                                                                 &thumb_width,
273                                                                                 &thumb_height,
274                                                                                 &origin_width,
275                                                                                 &origin_height);
276
277         if (err != MS_MEDIA_ERR_NONE) {
278                 thumb_err("There is no exif data");
279                 return err;
280         }
281
282         thumb_dbg("thumb width : height [%d:%d]", thumb_width, thumb_height);
283         thumb_dbg("origin width : height [%d:%d]", origin_width, origin_height);
284         thumb_info->origin_height = origin_height;
285         thumb_info->origin_width = origin_width;
286
287         if (thumb_width < required_width) {
288                 thumb_err("Thumb data in exif is too small");
289                 SAFE_FREE(thumb);
290                 return MS_MEDIA_ERR_INVALID_PARAMETER;
291         }
292
293         if (is_rotated) {
294                 err = mm_util_decode_from_jpeg_memory(&decoded, thumb, size, MM_UTIL_JPEG_FMT_RGB888);
295                 SAFE_FREE(thumb);
296                 if (err != MS_MEDIA_ERR_NONE) {
297                         thumb_err("mm_util_decode_from_jpeg_turbo_memory failed : %d", err);
298                         return err;
299                 }
300
301                 thumb_width = decoded.width;
302                 thumb_height = decoded.height;
303
304                 if (is_rotated) {
305 #if THUMB_PERFORMANCE_ENHANCED
306                         int rot_type = MM_UTIL_ROTATE_0;
307                         if (orientation == ROT_90) {
308                                 rot_type = MM_UTIL_ROTATE_90;
309                         } else if (orientation == ROT_180) {
310                                 rot_type = MM_UTIL_ROTATE_180;
311                         } else if (orientation == ROT_270) {
312                                 rot_type = MM_UTIL_ROTATE_270;
313                         }
314                         err = _media_thumb_rotate_thumb(decoded.data, decoded.size, &(decoded.width), &(decoded.height), rot_type, MM_UTIL_JPEG_FMT_RGB888);
315                         if (err != MS_MEDIA_ERR_NONE) {
316                                 thumb_err("_media_thumb_rotate_thumb falied: %d", err);
317                                 SAFE_FREE(thumb_info->data);
318                                 return err;
319                         }
320                         //thumb_dbg("Width : %d, Height : %d", decoded.width, decoded.height);
321                         thumb_info->data = decoded.data;
322                         thumb_info->size = decoded.size;
323                         thumb_info->width = decoded.width;
324                         thumb_info->height = decoded.height;
325 #else
326                         /* Start to decode to rotate */
327                         unsigned char *rotated = NULL;
328                         unsigned int r_w = decoded.height;
329                         unsigned int r_h = decoded.width;
330                         unsigned int r_size = 0;
331                         mm_util_img_rotate_type rot_type = MM_UTIL_ROTATE_0;
332
333                         int i, rotate_cnt = 0;
334
335                         rot_type = MM_UTIL_ROTATE_90;
336                         if (orientation == ROT_90) {
337                                 rotate_cnt = 1;
338                         } else if (orientation == ROT_180) {
339                                 rotate_cnt = 2;
340                         } else if (orientation == ROT_270) {
341                                 rotate_cnt = 3;
342                         }
343
344                         for (i = 0; i < rotate_cnt; i++) {
345                                 if (i == 1) {
346                                         r_w = decoded.width;
347                                         r_h = decoded.height;
348                                 }
349
350                                 err = mm_util_get_image_size(MM_UTIL_IMG_FMT_RGB888, r_w, r_h, &r_size);
351                                 if (err != MS_MEDIA_ERR_NONE) {
352                                         thumb_err("mm_util_get_image_size failed : %d", err);
353                                         SAFE_FREE(decoded.data);
354                                         return err;
355                                 }
356
357                                 rotated = (unsigned char *)malloc(r_size);
358                                 err = mm_util_rotate_image(decoded.data, decoded.width, decoded.height,
359                                                                                         MM_UTIL_IMG_FMT_RGB888,
360                                                                                         rotated, &r_w, &r_h,
361                                                                                         rot_type);
362
363                                 if (err != MS_MEDIA_ERR_NONE) {
364                                         thumb_err("mm_util_rotate_image failed : %d", err);
365                                         SAFE_FREE(decoded.data);
366                                         SAFE_FREE(rotated);
367                                         return err;
368                                 } else {
369                                         thumb_err("mm_util_rotate_image succeed");
370                                 }
371
372                                 SAFE_FREE(decoded.data);
373                                 decoded.data = rotated;
374                                 decoded.width = r_w;
375                                 decoded.height = r_h;
376                         }
377
378                         //thumb_dbg("Width : %d, Height : %d", r_w, r_h);
379                         thumb_info->data = rotated;
380                         thumb_info->size = r_size;
381                         thumb_info->width = r_w;
382                         thumb_info->height = r_h;
383 #endif
384                 } else {
385                         thumb_warn("Unknown orientation");
386                         SAFE_FREE(decoded.data);
387                         return MS_MEDIA_ERR_INVALID_PARAMETER;
388                 }
389         } else {
390                 /*in this case, just write raw data in file */
391                 thumb_dbg_slog("Thumb is :%s", thumb_path);
392
393                 int nwrite;
394                 int fd = open(thumb_path, O_RDWR | O_CREAT | O_EXCL | O_SYNC, 0644);
395                 if (fd < 0) {
396                         if (errno == EEXIST) {
397                                 thumb_err("thumb alread exist!");
398                         } else {
399                                 thumb_err("open failed");
400                                 SAFE_FREE(thumb);
401                                 return MS_MEDIA_ERR_INVALID_PARAMETER;
402                         }
403                 } else {
404                         nwrite = write(fd, thumb, size);
405                         if (nwrite < 0) {
406                                 thumb_err("write failed");
407                                 close(fd);
408
409                                 SAFE_FREE(thumb);
410                                 return MS_MEDIA_ERR_INVALID_PARAMETER;
411                         }
412                         close(fd);
413                 }
414
415                 SAFE_FREE(thumb);
416                 thumb_info->data = NULL;
417                 thumb_info->size = size;
418                 thumb_info->width = thumb_width;
419                 thumb_info->height = thumb_height;
420                 thumb_info->is_saved = TRUE;
421         }
422
423         return err;
424 }
425
426 int _media_thumb_resize_data(unsigned char *src_data,
427                                                         int src_width,
428                                                         int src_height,
429                                                         mm_util_img_format src_format,
430                                                         media_thumb_info *thumb_info,
431                                                         int dst_width,
432                                                         int dst_height)
433 {
434         int thumb_width = dst_width;
435         int thumb_height = dst_height;
436         unsigned int buf_size = 0;
437
438         if (mm_util_get_image_size(src_format, thumb_width, thumb_height, &buf_size) < 0) {
439                 thumb_err("Failed to get buffer size");
440                 return MS_MEDIA_ERR_INTERNAL;
441         }
442
443         thumb_dbg("mm_util_get_image_size : %d", buf_size);
444
445         unsigned char *dst = (unsigned char *)malloc(buf_size);
446
447         if (dst == NULL) {
448                 thumb_err("malloc fails");
449                 return MS_MEDIA_ERR_OUT_OF_MEMORY;
450         }
451
452         if (mm_util_resize_image((unsigned char *)src_data, src_width,
453                         src_height, src_format,
454                         dst, (unsigned int *)&thumb_width,
455                         (unsigned int *)&thumb_height) < 0) {
456                 thumb_err("Failed to resize the thumbnails");
457
458                 SAFE_FREE(dst);
459
460                 return MS_MEDIA_ERR_INTERNAL;
461         }
462
463         thumb_info->size = buf_size;
464         thumb_info->width = thumb_width;
465         thumb_info->height = thumb_height;
466         thumb_info->data = malloc(buf_size);
467         if (thumb_info->data != NULL) {
468                 memcpy(thumb_info->data, dst, buf_size);
469         } else {
470                 thumb_err("malloc fails");
471                 SAFE_FREE(dst);
472                 return MS_MEDIA_ERR_OUT_OF_MEMORY;
473         }
474         SAFE_FREE(dst);
475
476         return MS_MEDIA_ERR_NONE;
477 }
478
479 int _media_thumb_get_wh_with_evas(const char *origin_path, int *width, int *height)
480 {
481         /* using evas to get w/h */
482         Ecore_Evas *ee = ecore_evas_buffer_new(0, 0);
483         if (!ee) {
484                 thumb_err("ecore_evas_buffer_new fails");
485                 return MS_MEDIA_ERR_INTERNAL;
486         }
487
488         Evas *evas = ecore_evas_get(ee);
489         if (!evas) {
490                 thumb_err("ecore_evas_get fails");
491                 ecore_evas_free(ee);
492                 return MS_MEDIA_ERR_INTERNAL;
493         }
494
495         Evas_Object *image_object = evas_object_image_add(evas);
496         if (!image_object) {
497                 thumb_err("evas_object_image_add fails");
498                 ecore_evas_free(ee);
499                 return MS_MEDIA_ERR_INTERNAL;
500         }
501
502         evas_object_image_file_set(image_object, origin_path, NULL);
503         evas_object_image_size_get(image_object, width, height);
504
505         thumb_dbg("Width:%d, Height:%d", *width, *height);
506
507         ecore_evas_free(ee);
508
509         return MS_MEDIA_ERR_NONE;
510 }
511
512 int _media_thumb_decode_with_evas(const char *origin_path,
513                                         int thumb_width, int thumb_height,
514                                         media_thumb_info *thumb_info, int need_scale, int orientation)
515 {
516         Ecore_Evas *resize_img_ee;
517
518         resize_img_ee = ecore_evas_buffer_new(thumb_width, thumb_height);
519         if (!resize_img_ee) {
520                 thumb_err("ecore_evas_buffer_new failed");
521                 return MS_MEDIA_ERR_INTERNAL;
522         }
523
524         Evas *resize_img_e = ecore_evas_get(resize_img_ee);
525         if (!resize_img_e) {
526                 thumb_err("ecore_evas_get failed");
527                 ecore_evas_free(resize_img_ee);
528                 return MS_MEDIA_ERR_INTERNAL;
529         }
530
531         Evas_Object *source_img = evas_object_image_add(resize_img_e);
532         if (!source_img) {
533                 thumb_err("evas_object_image_add failed");
534                 ecore_evas_free(resize_img_ee);
535                 return MS_MEDIA_ERR_INTERNAL;
536         }
537
538         evas_object_image_file_set(source_img, origin_path, NULL);
539
540         /* Get w/h of original image */
541         int width = 0;
542         int height = 0;
543
544         evas_object_image_size_get(source_img, &width, &height);
545         thumb_info->origin_width = width;
546         thumb_info->origin_height = height;
547         //thumb_dbg("origin width:%d, origin height:%d", width, height);
548
549         if ((need_scale == 1) && (width * height > THUMB_MAX_ALLOWED_MEM_FOR_THUMB)) {
550                 thumb_warn("This is too large image. so this's scale is going to be down");
551                 evas_object_image_load_scale_down_set(source_img, 10);
552         }
553
554         if (orientation != TRANSPOSE)
555                 evas_object_image_load_orientation_set(source_img, 1);
556
557         int rotated_orig_w = 0;
558         int rotated_orig_h = 0;
559
560         if (orientation == ROT_90 || orientation == ROT_270) {
561                 rotated_orig_w = height;
562                 rotated_orig_h = width;
563         } else {
564                 rotated_orig_w = width;
565                 rotated_orig_h = height;
566         }
567         //thumb_dbg("rotated - origin width:%d, origin height:%d", rotated_orig_w, rotated_orig_h);
568
569         int err = MS_MEDIA_ERR_NONE;
570
571         err = _media_thumb_get_proper_thumb_size(rotated_orig_w, rotated_orig_h, &thumb_width, &thumb_height);
572         if (err != MS_MEDIA_ERR_NONE) {
573                 thumb_err("_media_thumb_get_proper_thumb_size failed: %d", err);
574                 ecore_evas_free(resize_img_ee);
575                 return err;
576         }
577
578         ecore_evas_resize(resize_img_ee, thumb_width, thumb_height);
579
580         evas_object_image_load_size_set(source_img, thumb_width, thumb_height);
581         evas_object_image_fill_set(source_img, 0, 0, thumb_width, thumb_height);
582         evas_object_image_filled_set(source_img, 1);
583
584         evas_object_resize(source_img, thumb_width, thumb_height);
585         evas_object_show(source_img);
586
587         /* Set alpha from original */
588         thumb_info->alpha = evas_object_image_alpha_get(source_img);
589         if (thumb_info->alpha) ecore_evas_alpha_set(resize_img_ee, EINA_TRUE);
590
591         /* Create target buffer and copy origin resized img to it */
592         Ecore_Evas *target_ee = ecore_evas_buffer_new(thumb_width, thumb_height);
593         if (!target_ee) {
594                 thumb_err("ecore_evas_buffer_new failed");
595                 ecore_evas_free(resize_img_ee);
596                 return MS_MEDIA_ERR_INTERNAL;
597         }
598
599         Evas *target_evas = ecore_evas_get(target_ee);
600         if (!target_evas) {
601                 thumb_err("ecore_evas_get failed");
602                 ecore_evas_free(resize_img_ee);
603                 ecore_evas_free(target_ee);
604                 return MS_MEDIA_ERR_INTERNAL;
605         }
606
607         Evas_Object *ret_image = evas_object_image_add(target_evas);
608         evas_object_image_size_set(ret_image, thumb_width, thumb_height);
609         evas_object_image_fill_set(ret_image, 0, 0, thumb_width, thumb_height);
610         evas_object_image_filled_set(ret_image, EINA_TRUE);
611
612         evas_object_image_data_set(ret_image, (int *)ecore_evas_buffer_pixels_get(resize_img_ee));
613         evas_object_image_data_update_add(ret_image, 0, 0, thumb_width, thumb_height);
614
615         unsigned int buf_size = 0;
616         if (mm_util_get_image_size(MM_UTIL_IMG_FMT_BGRA8888, thumb_width, thumb_height, &buf_size) < 0) {
617                 thumb_err("mm_util_get_image_size failed");
618
619                 ecore_evas_free(resize_img_ee);
620                 ecore_evas_free(target_ee);
621
622                 return MS_MEDIA_ERR_INTERNAL;
623         }
624         //thumb_dbg("mm_util_get_image_size : %d", buf_size);
625
626         thumb_info->size = buf_size;
627         thumb_info->width = thumb_width;
628         thumb_info->height = thumb_height;
629         thumb_info->data = malloc(buf_size);
630         if (thumb_info->data == NULL) {
631                 thumb_err("Failed to allocate memory");
632                 ecore_evas_free(resize_img_ee);
633                 ecore_evas_free(target_ee);
634
635                 return MS_MEDIA_ERR_OUT_OF_MEMORY;
636         }
637
638         void *image_data = evas_object_image_data_get(ret_image, 1);
639         if (image_data != NULL) {
640                 memcpy(thumb_info->data, image_data, buf_size);
641         } else {
642                 thumb_err("image_data is NULL. evas_object_image_data_get failed");
643         }
644
645         ecore_evas_free(target_ee);
646         ecore_evas_free(resize_img_ee);
647
648         return err;
649 }
650
651 #if THUMB_PERFORMANCE_ENHANCED
652 int _media_thumb_convert_video(const unsigned char *src_data, const int src_size,
653                                                         unsigned char **dst_data,
654                                                         unsigned int *buf_size,
655                                                         int width,
656                                                         int height,
657                                                         mm_util_img_format src_format,
658                                                         mm_util_img_format dst_format)
659 {
660         int err = MS_MEDIA_ERR_NONE;
661
662         thumb_dbg("src format:%d, dst format:%d", src_format, dst_format);
663
664         if (mm_util_get_image_size(dst_format, width, height, buf_size) < 0) {
665                 thumb_err("mm_util_get_image_size failed");
666                 return MS_MEDIA_ERR_INTERNAL;
667         }
668
669         thumb_dbg("mm_util_get_image_size : %d", *buf_size);
670
671         *dst_data = (unsigned char *)malloc(*buf_size);
672
673         if (*dst_data == NULL) {
674                 thumb_err("Failed to allocate memory");
675                 return MS_MEDIA_ERR_OUT_OF_MEMORY;
676         }
677
678         if (src_format == MM_UTIL_IMG_FMT_RGB888 &&
679                 dst_format == MM_UTIL_IMG_FMT_BGRA8888) {
680
681                 int i = 0, j;
682                 for (j = 0; ((j < src_size) && (i < *buf_size)); j += 3) {
683                         (*dst_data)[i++] = (src_data[j + 2]);
684                         (*dst_data)[i++] = (src_data[j + 1]);
685                         (*dst_data)[i++] = (src_data[j]);
686                         (*dst_data)[i++] = 0x0;
687                 }
688
689         } else {
690                 err = mm_util_convert_colorspace(src_data,
691                                                 width,
692                                                 height,
693                                                 src_format,
694                                                 *dst_data,
695                                                 dst_format);
696
697                 if (err < 0) {
698                         thumb_err("Failed to change from rgb888 to argb8888 %d", err);
699                         SAFE_FREE(*dst_data);
700                         return MS_MEDIA_ERR_INTERNAL;
701                 }
702         }
703
704         thumb_dbg("_media_thumb_convert_video success");
705
706         return err;
707 }
708
709 int _media_thumb_resize_video_with_evas(const char *image,
710                                         int thumb_width, int thumb_height,
711                                         media_thumb_info *thumb_info)
712 {
713         Ecore_Evas *resize_img_ee;
714
715         if (image == NULL) {
716                 thumb_err("Invalid parameter");
717                 return MS_MEDIA_ERR_INVALID_PARAMETER;
718         }
719         resize_img_ee = ecore_evas_buffer_new(thumb_width, thumb_height);
720         if (!resize_img_ee) {
721                 thumb_err("ecore_evas_buffer_new failed");
722                 return MS_MEDIA_ERR_INTERNAL;
723         }
724
725         Evas *resize_img_e = ecore_evas_get(resize_img_ee);
726         if (!resize_img_e) {
727                 thumb_err("ecore_evas_get failed");
728                 ecore_evas_free(resize_img_ee);
729                 return MS_MEDIA_ERR_INTERNAL;
730         }
731
732         Evas_Object *source_img = evas_object_image_add(resize_img_e);
733         if (!source_img) {
734                 thumb_err("evas_object_image_add failed");
735                 ecore_evas_free(resize_img_ee);
736                 return MS_MEDIA_ERR_INTERNAL;
737         }
738
739         evas_object_image_size_set(source_img, thumb_info->origin_width, thumb_info->origin_height);
740         evas_object_image_colorspace_set(source_img, EVAS_COLORSPACE_ARGB8888);
741         evas_object_image_fill_set(source_img, 0, 0, thumb_info->origin_width, thumb_info->origin_height);
742         evas_object_image_filled_set(source_img, EINA_TRUE);
743
744         evas_object_image_data_set(source_img, (int *)image);
745         evas_object_image_data_update_add(source_img, 0, 0, thumb_info->origin_width, thumb_info->origin_height);
746
747         if (thumb_info->origin_width * thumb_info->origin_height > THUMB_MAX_ALLOWED_MEM_FOR_THUMB) {
748                 thumb_warn("This is too large image. so this's scale is going to be down");
749                 evas_object_image_load_scale_down_set(source_img, 10);
750         }
751
752         ecore_evas_resize(resize_img_ee, thumb_width, thumb_height);
753
754         evas_object_image_load_size_set(source_img, thumb_width, thumb_height);
755         evas_object_image_fill_set(source_img, 0, 0, thumb_width, thumb_height);
756         evas_object_image_filled_set(source_img, EINA_TRUE);
757
758         evas_object_resize(source_img, thumb_width, thumb_height);
759         evas_object_show(source_img);
760
761         /* Set alpha from original */
762         thumb_info->alpha = evas_object_image_alpha_get(source_img);
763         if (thumb_info->alpha)
764                 ecore_evas_alpha_set(resize_img_ee, EINA_TRUE);
765
766         /* Create target buffer and copy origin resized img to it */
767         Ecore_Evas *target_ee = ecore_evas_buffer_new(thumb_width, thumb_height);
768         if (!target_ee) {
769                 thumb_err("ecore_evas_buffer_new failed");
770                 ecore_evas_free(resize_img_ee);
771                 return MS_MEDIA_ERR_INTERNAL;
772         }
773
774         Evas *target_evas = ecore_evas_get(target_ee);
775         if (!target_evas) {
776                 thumb_err("ecore_evas_get failed");
777                 ecore_evas_free(resize_img_ee);
778                 ecore_evas_free(target_ee);
779                 return MS_MEDIA_ERR_INTERNAL;
780         }
781
782         Evas_Object *ret_image = evas_object_image_add(target_evas);
783         evas_object_image_size_set(ret_image, thumb_width, thumb_height);
784         evas_object_image_fill_set(ret_image, 0, 0, thumb_width, thumb_height);
785         evas_object_image_filled_set(ret_image, EINA_TRUE);
786
787         evas_object_image_data_set(ret_image, (int *)ecore_evas_buffer_pixels_get(resize_img_ee));
788         evas_object_image_data_update_add(ret_image, 0, 0, thumb_width, thumb_height);
789
790         unsigned int buf_size = 0;
791         if (mm_util_get_image_size(MM_UTIL_IMG_FMT_BGRA8888, thumb_width, thumb_height, &buf_size) < 0) {
792                 thumb_err("mm_util_get_image_size failed");
793
794                 ecore_evas_free(resize_img_ee);
795                 ecore_evas_free(target_ee);
796
797                 return MS_MEDIA_ERR_INTERNAL;
798         }
799
800         thumb_info->size = buf_size;
801         thumb_info->width = thumb_width;
802         thumb_info->height = thumb_height;
803         thumb_info->data = malloc(buf_size);
804         if (thumb_info->data == NULL) {
805                 thumb_err("Failed to allocate memory");
806                 ecore_evas_free(resize_img_ee);
807                 ecore_evas_free(target_ee);
808
809                 return MS_MEDIA_ERR_OUT_OF_MEMORY;
810         }
811
812         void *image_data = evas_object_image_data_get(ret_image, EINA_TRUE);
813         if (image_data != NULL) {
814                 memcpy(thumb_info->data, image_data, buf_size);
815         } else {
816                 thumb_err("image_data is NULL. evas_object_image_data_get failed");
817         }
818
819         ecore_evas_free(target_ee);
820         ecore_evas_free(resize_img_ee);
821
822         thumb_dbg("_media_thumb_resize_video_with_evas success");
823
824         return MS_MEDIA_ERR_NONE;
825 }
826
827 int _media_thumb_rotate_argb(unsigned char *source, const unsigned int size, int format, int *ori_width, int *ori_height)
828 {
829         int dpp = 0; /* data per pixel */
830         int x = 0, y = 0;
831         int i = 0;
832         int width = 0, height = 0;
833         unsigned char *temp_buf = NULL;
834
835         if (format == MM_UTIL_JPEG_FMT_BGRA8888) {
836                 dpp = 4;
837         } else if (format == MM_UTIL_JPEG_FMT_RGB888) {
838                 dpp = 3;
839         } else {
840                 thumb_err("Invalid parameter");
841                 return MS_MEDIA_ERR_INVALID_PARAMETER;
842         }
843
844         temp_buf = malloc(size);
845         if (temp_buf == NULL) {
846                 thumb_err("Failed to allocate memory");
847                 return MS_MEDIA_ERR_OUT_OF_MEMORY;
848         }
849         /* initialize */
850         memset(temp_buf, 0x00, size);
851         width = *ori_width;
852         height = *ori_height;
853
854         /* rotate image to 90 degree clockwise */
855         for (y = 0; y < height; y++)
856         {
857                 for (x = 0; x < width; x++) {
858                         for (i = 0; i < dpp; i++) {
859                                 temp_buf[(x * height + (height - y - 1)) * dpp + i] = source[(y * width + x) * dpp + i];
860                         }
861                 }
862         }
863
864         /* copy image from temp buffer to original buffer */
865         memcpy(source, temp_buf, size);
866         SAFE_FREE(temp_buf);
867
868         /* swap width & height due to rotate 90 degree */
869         *ori_width = height;
870         *ori_height = width;
871
872         return MS_MEDIA_ERR_NONE;
873 }
874
875 int _media_thumb_rotate_thumb(unsigned char *data, int size, int *width, int *height, int orientation, int format)
876 {
877         int err = MS_MEDIA_ERR_NONE;
878         int i = 0, count = 0;
879
880         if (orientation == MM_UTIL_ROTATE_90) {
881                 count = 1;
882         } else if (orientation == MM_UTIL_ROTATE_180) {
883                 count = 2;
884         } else if (orientation == MM_UTIL_ROTATE_270) {
885                 count = 3;
886         }
887
888         for (i = 0; i < count; i++) {
889                 err = _media_thumb_rotate_argb(data, size, format, width, height);
890                 if (err != MS_MEDIA_ERR_NONE) {
891                         thumb_err("Failed to rotate video thumbnail %d", err);
892                         return err;
893                 }
894 //              thumb_dbg("[%d rotate] width:%d, height:%d", (i + 1) * 90, thumb_info->width, thumb_info->height);
895         }
896
897         thumb_dbg("_media_thumb_rotate_thumb success");
898         return MS_MEDIA_ERR_NONE;
899 }
900 #endif
901
902 mm_util_img_format _media_thumb_get_format(media_thumb_format src_format)
903 {
904         switch (src_format) {
905                 case MEDIA_THUMB_BGRA:
906                         return MM_UTIL_IMG_FMT_BGRA8888;
907                 case MEDIA_THUMB_RGB888:
908                         return MM_UTIL_IMG_FMT_RGB888;
909                 default:
910                         return MS_MEDIA_ERR_INVALID_PARAMETER;
911         }
912 }
913
914 int _media_thumb_convert_data(media_thumb_info *thumb_info,
915                                                         int thumb_width,
916                                                         int thumb_height,
917                                                         mm_util_img_format src_format,
918                                                         mm_util_img_format dst_format)
919 {
920         int err = MS_MEDIA_ERR_NONE;
921         unsigned int buf_size = 0;
922         unsigned char *src_data = thumb_info->data;
923         unsigned char *dst_data = NULL;
924
925         thumb_dbg("src format:%d, dst format:%d", src_format, dst_format);
926
927         if (mm_util_get_image_size(dst_format, thumb_width, thumb_height, &buf_size) < 0) {
928                 thumb_err("mm_util_get_image_size failed");
929                 return MS_MEDIA_ERR_INTERNAL;
930         }
931
932         thumb_dbg("mm_util_get_image_size : %d", buf_size);
933
934         dst_data = (unsigned char *)malloc(buf_size);
935
936         if (dst_data == NULL) {
937                 thumb_err("Failed to allocate memory");
938                 return MS_MEDIA_ERR_OUT_OF_MEMORY;
939         }
940
941         if (src_format == MM_UTIL_IMG_FMT_RGB888 &&
942                 dst_format == MM_UTIL_IMG_FMT_BGRA8888) {
943
944                 int i = 0, j;
945                 for (j = 0; j < thumb_width * 3 * thumb_height;
946                                 j += 3) {
947                         dst_data[i++] = (src_data[j + 2]);
948                         dst_data[i++] = (src_data[j + 1]);
949                         dst_data[i++] = (src_data[j]);
950                         dst_data[i++] = 0x0;
951                 }
952
953         } else {
954                 err = mm_util_convert_colorspace(src_data,
955                                                 thumb_width,
956                                                 thumb_height,
957                                                 src_format,
958                                                 dst_data,
959                                                 dst_format);
960
961                 if (err < 0) {
962                         thumb_err("Failed to change from rgb888 to argb8888 %d", err);
963                         SAFE_FREE(dst_data);
964                         return MS_MEDIA_ERR_INTERNAL;
965                 }
966         }
967
968         SAFE_FREE(thumb_info->data);
969         thumb_info->data = dst_data;
970         thumb_info->size = buf_size;
971
972         thumb_dbg("_media_thumb_convert_data success");
973
974         return err;
975 }
976
977 int _media_thumb_convert_format(media_thumb_info *thumb_info,
978                                                         media_thumb_format src_format,
979                                                         media_thumb_format dst_format)
980 {
981         int err = MS_MEDIA_ERR_NONE;
982
983         if (src_format == dst_format) {
984                 //thumb_dbg("src_format == dst_format");
985                 return err;
986         }
987
988         mm_util_img_format src_mm_format;
989         mm_util_img_format dst_mm_format;
990
991         src_mm_format = _media_thumb_get_format(src_format);
992         dst_mm_format = _media_thumb_get_format(dst_format);
993
994         if ((int)src_mm_format == -1 || (int)dst_mm_format == -1) {
995                 thumb_err("Format is invalid");
996                 return MS_MEDIA_ERR_INVALID_PARAMETER;
997         }
998
999         err = _media_thumb_convert_data(thumb_info,
1000                                         thumb_info->width,
1001                                         thumb_info->height,
1002                                         src_mm_format,
1003                                         dst_mm_format);
1004
1005         if (err != MS_MEDIA_ERR_NONE) {
1006                 thumb_err("media_thumb_convert_format failed : %d", err);
1007                 return err;
1008         }
1009
1010         return err;
1011 }
1012
1013 int _media_thumb_agif(const char *origin_path,
1014                                         int image_width,
1015                                         int image_height,
1016                                         int thumb_width,
1017                                         int thumb_height,
1018                                         media_thumb_format format,
1019                                         media_thumb_info *thumb_info)
1020 {
1021         int err = MS_MEDIA_ERR_NONE;
1022         unsigned int *thumb = NULL;
1023
1024         thumb = ImgGetFirstFrameAGIFAtSize(origin_path, image_width, image_height);
1025
1026         if (!thumb) {
1027                 thumb_err("Frame data is NULL!!");
1028                 return MS_MEDIA_ERR_INTERNAL;
1029         }
1030
1031         err = _media_thumb_get_proper_thumb_size(thumb_info->origin_width, thumb_info->origin_height, &thumb_width, &thumb_height);
1032         if (err != MS_MEDIA_ERR_NONE) {
1033                 thumb_err("_media_thumb_get_proper_thumb_size failed: %d", err);
1034                 SAFE_FREE(thumb);
1035                 return err;
1036         }
1037
1038         err = _media_thumb_resize_data((unsigned char *)thumb,
1039                                                                         image_width,
1040                                                                         image_height,
1041                                                                         MM_UTIL_IMG_FMT_RGB888,
1042                                                                         thumb_info,
1043                                                                         thumb_width,
1044                                                                         thumb_height);
1045
1046         if (err != MS_MEDIA_ERR_NONE) {
1047                 thumb_err("_media_thumb_resize_data failed: %d", err);
1048                 SAFE_FREE(thumb);
1049                 return err;
1050         }
1051
1052         SAFE_FREE(thumb);
1053
1054         err = _media_thumb_convert_format(thumb_info, MEDIA_THUMB_RGB888, format);
1055         if (err != MS_MEDIA_ERR_NONE) {
1056                 thumb_err("_media_thumb_convert_format falied: %d", err);
1057                 SAFE_FREE(thumb_info->data);
1058                 return err;
1059         }
1060
1061         return err;
1062 }
1063
1064 int _media_thumb_png(const char *origin_path,
1065                                         int thumb_width,
1066                                         int thumb_height,
1067                                         media_thumb_format format,
1068                                         media_thumb_info *thumb_info)
1069 {
1070         int err = MS_MEDIA_ERR_NONE;
1071         err = _media_thumb_decode_with_evas(origin_path, thumb_width, thumb_height, thumb_info, 1, NORMAL);
1072
1073         if (err != MS_MEDIA_ERR_NONE) {
1074                 thumb_err("decode_with_evas failed : %d", err);
1075                 return err;
1076         }
1077
1078         err = _media_thumb_convert_format(thumb_info, MEDIA_THUMB_BGRA, format);
1079         if (err != MS_MEDIA_ERR_NONE) {
1080                 thumb_err("_media_thumb_convert_format falied: %d", err);
1081                 SAFE_FREE(thumb_info->data);
1082                 return err;
1083         }
1084
1085         return err;
1086 }
1087
1088 int _media_thumb_bmp(const char *origin_path,
1089                                         int thumb_width,
1090                                         int thumb_height,
1091                                         media_thumb_format format,
1092                                         media_thumb_info *thumb_info)
1093 {
1094         int err = MS_MEDIA_ERR_NONE;
1095         err = _media_thumb_decode_with_evas(origin_path, thumb_width, thumb_height, thumb_info, 1, NORMAL);
1096
1097         if (err != MS_MEDIA_ERR_NONE) {
1098                 thumb_err("decode_with_evas failed : %d", err);
1099                 return err;
1100         }
1101
1102         err = _media_thumb_convert_format(thumb_info, MEDIA_THUMB_BGRA, format);
1103         if (err != MS_MEDIA_ERR_NONE) {
1104                 thumb_err("_media_thumb_convert_format falied: %d", err);
1105                 SAFE_FREE(thumb_info->data);
1106                 return err;
1107         }
1108
1109         return err;
1110 }
1111
1112 int _media_thumb_wbmp(const char *origin_path,
1113                                         int thumb_width,
1114                                         int thumb_height,
1115                                         media_thumb_format format,
1116                                         media_thumb_info *thumb_info)
1117 {
1118         int err = MS_MEDIA_ERR_NONE;
1119         err = _media_thumb_decode_with_evas(origin_path, thumb_width, thumb_height, thumb_info, 1, NORMAL);
1120
1121         if (err != MS_MEDIA_ERR_NONE) {
1122                 thumb_err("decode_with_evas failed : %d", err);
1123                 return err;
1124         }
1125
1126         err = _media_thumb_convert_format(thumb_info, MEDIA_THUMB_BGRA, format);
1127         if (err != MS_MEDIA_ERR_NONE) {
1128                 thumb_err("_media_thumb_convert_format falied: %d", err);
1129                 SAFE_FREE(thumb_info->data);
1130                 return err;
1131         }
1132
1133         return err;
1134 }
1135
1136 int _media_thumb_gif(const char *origin_path,
1137                                         int thumb_width,
1138                                         int thumb_height,
1139                                         media_thumb_format format,
1140                                         media_thumb_info *thumb_info)
1141 {
1142         int err = MS_MEDIA_ERR_NONE;
1143         err = _media_thumb_decode_with_evas(origin_path, thumb_width, thumb_height, thumb_info, 1, NORMAL);
1144
1145         if (err != MS_MEDIA_ERR_NONE) {
1146                 thumb_err("decode_with_evas failed : %d", err);
1147                 return err;
1148         }
1149
1150         err = _media_thumb_convert_format(thumb_info, MEDIA_THUMB_BGRA, format);
1151         if (err != MS_MEDIA_ERR_NONE) {
1152                 thumb_err("_media_thumb_convert_format falied: %d", err);
1153                 SAFE_FREE(thumb_info->data);
1154                 return err;
1155         }
1156
1157         return err;
1158 }
1159
1160 int _media_thumb_jpeg(const char *origin_path,
1161                                         const char *thumb_path,
1162                                         int thumb_width,
1163                                         int thumb_height,
1164                                         media_thumb_format format,
1165                                         media_thumb_info *thumb_info)
1166 {
1167         int err = MS_MEDIA_ERR_NONE;
1168         int thumb_done = 0;
1169         int orientation = NORMAL;
1170         ExifData *ed = NULL;
1171
1172         if (!thumb_info->is_raw) {
1173                 /* Load an ExifData object from an EXIF file */
1174                 ed = exif_data_new_from_file(origin_path);
1175
1176                 if (ed) {
1177                         /* First, Get orientation from exif */
1178                         err = _media_thumb_get_exif_info(ed, NULL, 0, &orientation, EXIF_IFD_0, EXIF_TAG_ORIENTATION);
1179
1180                         if (err != MS_MEDIA_ERR_NONE) {
1181                                 thumb_warn("_media_thumb_get_exif_info failed");
1182                         }
1183
1184                         /* Second, Get thumb from exif */
1185                         err = _media_thumb_get_thumb_from_exif(ed, origin_path, thumb_path, orientation, thumb_width, thumb_height, thumb_info);
1186
1187                         if (err != MS_MEDIA_ERR_NONE) {
1188                                 thumb_dbg("_media_thumb_get_thumb_from_exif failed");
1189                         } else {
1190                                 thumb_done = 1;
1191                                 thumb_dbg("_media_thumb_get_thumb_from_exif succeed");
1192
1193                                 /* The case that original image's size is not in exif header. Use evas to get w/h */
1194                                 if (thumb_info->origin_width == 0 || thumb_info->origin_height == 0) {
1195                                         thumb_warn("original image's size is not in exif header. Use evas to get w/h");
1196                                         err = _media_thumb_get_wh_with_evas(origin_path, &(thumb_info->origin_width), &(thumb_info->origin_height));
1197                                         if (err != MS_MEDIA_ERR_NONE) {
1198                                                 thumb_err("Couldn't get w/h using evas : %s", origin_path);
1199                                         } else {
1200                                                 thumb_dbg("origin w : %d, origin h : %d", thumb_info->origin_width, thumb_info->origin_height);
1201                                         }
1202                                 }
1203
1204                                 if (thumb_info->is_saved == FALSE) {
1205                                         mm_util_img_format dst_format = _media_thumb_get_format(format);
1206
1207                                         err = _media_thumb_convert_data(thumb_info,
1208                                                                         thumb_info->width,
1209                                                                         thumb_info->height,
1210                                                                         MM_UTIL_IMG_FMT_RGB888,
1211                                                                         dst_format);
1212
1213                                         if (err != MS_MEDIA_ERR_NONE) {
1214                                                 thumb_err("_media_thumb_convert_data failed : %d", err);
1215                                                 exif_data_unref(ed);
1216                                                 return err;
1217                                         }
1218                                 }
1219                         }
1220
1221                         exif_data_unref(ed);
1222                 }
1223         }
1224
1225         if (!thumb_done) {
1226
1227                 err = _media_thumb_decode_with_evas(origin_path, thumb_width, thumb_height, thumb_info, 1, orientation);
1228
1229                 if (err != MS_MEDIA_ERR_NONE) {
1230                         thumb_err("decode_with_evas failed : %d", err);
1231                         return err;
1232                 }
1233
1234                 err = _media_thumb_convert_format(thumb_info, MEDIA_THUMB_BGRA, format);
1235                 if (err != MS_MEDIA_ERR_NONE) {
1236                         thumb_err("_media_thumb_convert_format falied: %d", err);
1237                         SAFE_FREE(thumb_info->data);
1238                         return err;
1239                 }
1240         }
1241
1242         return err;
1243 }
1244
1245 int _media_thumb_image(const char *origin_path,
1246                                         const char *thumb_path,
1247                                         int thumb_width,
1248                                         int thumb_height,
1249                                         media_thumb_format format,
1250                                         media_thumb_info *thumb_info)
1251 {
1252         int err = MS_MEDIA_ERR_NONE;
1253         ImgCodecType image_type = 0;
1254         unsigned int origin_w = 0;
1255         unsigned int origin_h = 0;
1256
1257         err = ImgGetImageInfoForThumb(origin_path, &image_type, &origin_w, &origin_h);
1258
1259         if (err != MS_MEDIA_ERR_NONE) {
1260                 thumb_warn("Getting image info is failed err: %d", err);
1261         }
1262
1263         thumb_info->origin_width = origin_w;
1264         thumb_info->origin_height = origin_h;
1265
1266         if ((image_type != IMG_CODEC_JPEG) &&
1267                 (origin_w * origin_h > THUMB_MAX_ALLOWED_MEM_FOR_THUMB)) {
1268                 thumb_warn("This original image is too big");
1269                 return MS_MEDIA_ERR_THUMB_TOO_BIG;
1270         }
1271
1272         if (image_type == IMG_CODEC_AGIF) {
1273                 err = _media_thumb_agif(origin_path, origin_w, origin_h, thumb_width, thumb_height, format, thumb_info);
1274         } else if (image_type == IMG_CODEC_JPEG) {
1275                 err = _media_thumb_jpeg(origin_path, thumb_path, thumb_width, thumb_height, format, thumb_info);
1276         } else if (image_type == IMG_CODEC_PNG) {
1277                 err = _media_thumb_png(origin_path, thumb_width, thumb_height, format, thumb_info);
1278         } else if (image_type == IMG_CODEC_GIF) {
1279                 err = _media_thumb_gif(origin_path, thumb_width, thumb_height, format, thumb_info);
1280         } else if (image_type == IMG_CODEC_BMP) {
1281                 err = _media_thumb_bmp(origin_path, thumb_width, thumb_height, format, thumb_info);
1282         } else {
1283                 char file_ext[10];
1284                 err = _media_thumb_get_file_ext(origin_path, file_ext, sizeof(file_ext));
1285                 if (err != MS_MEDIA_ERR_NONE) {
1286                         thumb_warn("_media_thumb_get_file_ext failed");
1287                 } else {
1288                         if (strcasecmp(file_ext, "wbmp") == 0) {
1289                                 image_type = IMG_CODEC_WBMP;
1290                                 int wbmp_width = 0;
1291                                 int wbmp_height = 0;
1292
1293                                 err = _media_thumb_get_wh_with_evas(origin_path, &wbmp_width, &wbmp_height);
1294                                 if (err != MS_MEDIA_ERR_NONE) {
1295                                         thumb_err("_media_thumb_get_wh_with_evas in WBMP : %d", err);
1296                                         return err;
1297                                 }
1298
1299                                 if (wbmp_width * wbmp_height > THUMB_MAX_ALLOWED_MEM_FOR_THUMB) {
1300                                         thumb_warn("This original image is too big");
1301                                         return MS_MEDIA_ERR_THUMB_TOO_BIG;
1302                                 }
1303
1304                                 thumb_info->origin_width = wbmp_width;
1305                                 thumb_info->origin_height = wbmp_height;
1306
1307                                 err = _media_thumb_wbmp(origin_path, thumb_width, thumb_height, format, thumb_info);
1308
1309                                 return err;
1310                         }
1311                 }
1312
1313                 thumb_warn("Unsupported image type");
1314                 return MS_MEDIA_ERR_INVALID_PARAMETER;
1315         }
1316
1317         return err;
1318 }
1319
1320 int _media_thumb_video(const char *origin_path,
1321                                         int thumb_width,
1322                                         int thumb_height,
1323                                         media_thumb_format format,
1324                                         media_thumb_info *thumb_info)
1325 {
1326         int err = MS_MEDIA_ERR_NONE;
1327
1328         MMHandleType content = (MMHandleType) NULL;
1329         void *frame = NULL;
1330         int video_track_num = 0;
1331         char *err_msg = NULL;
1332         int is_drm = 0;
1333         int size = 0;
1334         int width = 0;
1335         int height = 0;
1336         bool drm_type = FALSE;
1337
1338         is_drm = drm_type;
1339
1340         /* Get Content Tag attribute for orientatin */
1341         MMHandleType tag = (MMHandleType) NULL;
1342         char *p = NULL;
1343         int cdis_value = 0;
1344         err = mm_file_create_tag_attrs(&tag, origin_path);
1345         mm_util_img_rotate_type rot_type = MM_UTIL_ROTATE_0;
1346
1347         if (err == FILEINFO_ERROR_NONE) {
1348                 err = mm_file_get_attrs(tag, &err_msg, MM_FILE_TAG_ROTATE, &p, &size, NULL);
1349                 if (err == FILEINFO_ERROR_NONE && size >= 0) {
1350                         if (p == NULL) {
1351                                 rot_type = MM_UTIL_ROTATE_0;
1352                         } else {
1353                                 if (strncmp(p, "90", size) == 0) {
1354                                         rot_type = MM_UTIL_ROTATE_90;
1355                                 } else if (strncmp(p, "180", size) == 0) {
1356                                         rot_type = MM_UTIL_ROTATE_180;
1357                                 } else if (strncmp(p, "270", size) == 0) {
1358                                         rot_type = MM_UTIL_ROTATE_270;
1359                                 } else {
1360                                         rot_type = MM_UTIL_ROTATE_0;
1361                                 }
1362                         }
1363                         thumb_dbg("There is tag rotate : %d", rot_type);
1364                 } else {
1365                         thumb_dbg("There is NOT tag rotate");
1366                         rot_type = MM_UTIL_ROTATE_0;
1367                         SAFE_FREE(err_msg);
1368                 }
1369
1370                 err = mm_file_get_attrs(tag, &err_msg, MM_FILE_TAG_CDIS, &cdis_value, NULL);
1371                 if (err != FILEINFO_ERROR_NONE) {
1372                         cdis_value = 0;
1373                         SAFE_FREE(err_msg);
1374                 }
1375
1376         } else {
1377                 rot_type = MM_UTIL_ROTATE_0;
1378                 cdis_value = 0;
1379         }
1380
1381         err = mm_file_destroy_tag_attrs(tag);
1382         if (err != FILEINFO_ERROR_NONE) {
1383                 thumb_err("fail to free tag attr - err(%x)", err);
1384         }
1385
1386         if (cdis_value == 1) {
1387                 thumb_warn("This is CDIS vlaue 1");
1388                 err = mm_file_create_content_attrs_safe(&content, origin_path);
1389         } else {
1390                 err = mm_file_create_content_attrs(&content, origin_path);
1391         }
1392
1393         if (err != FILEINFO_ERROR_NONE) {
1394                 thumb_err("mm_file_create_content_attrs fails : %d", err);
1395                 return MS_MEDIA_ERR_INTERNAL;
1396         }
1397
1398         err = mm_file_get_attrs(content, &err_msg, MM_FILE_CONTENT_VIDEO_TRACK_COUNT, &video_track_num, NULL);
1399         if (err != FILEINFO_ERROR_NONE) {
1400                 thumb_err("mm_file_get_attrs fails : %s", err_msg);
1401                 SAFE_FREE(err_msg);
1402                 mm_file_destroy_content_attrs(content);
1403                 return MS_MEDIA_ERR_INTERNAL;
1404         }
1405
1406         /* MMF api handle both normal and DRM video */
1407         if (video_track_num > 0 || is_drm) {
1408
1409                 err = mm_file_get_attrs(content, &err_msg,
1410                                         MM_FILE_CONTENT_VIDEO_WIDTH,
1411                                         &width,
1412                                         MM_FILE_CONTENT_VIDEO_HEIGHT,
1413                                         &height,
1414                                         MM_FILE_CONTENT_VIDEO_THUMBNAIL, &frame, /* raw image is RGB888 format */
1415                                         &size, NULL);
1416
1417                 if (err != FILEINFO_ERROR_NONE) {
1418                         thumb_err("mm_file_get_attrs fails : %s", err_msg);
1419                         SAFE_FREE(err_msg);
1420                         mm_file_destroy_content_attrs(content);
1421                         return MS_MEDIA_ERR_INTERNAL;
1422                 }
1423
1424                 thumb_dbg("video width: %d", width);
1425                 thumb_dbg("video height: %d", height);
1426                 thumb_dbg("thumbnail size: %d", size);
1427                 thumb_dbg("frame: 0x%x", frame);
1428                 thumb_dbg("orientation: %d", rot_type);
1429
1430                 if (frame == NULL || width == 0 || height == 0) {
1431                         thumb_err("Failed to get frame data");
1432                         mm_file_destroy_content_attrs(content);
1433                         return MS_MEDIA_ERR_INTERNAL;
1434                 }
1435
1436                 thumb_info->origin_width = width;
1437                 thumb_info->origin_height = height;
1438
1439                 err = _media_thumb_get_proper_thumb_size(width, height, &thumb_width, &thumb_height);
1440 #if THUMB_PERFORMANCE_ENHANCED
1441                 unsigned int new_size = 0;
1442                 unsigned char *new_frame = NULL;
1443                 err = _media_thumb_convert_video(frame, size, &new_frame, &new_size, width, height, MM_UTIL_IMG_FMT_RGB888, MM_UTIL_IMG_FMT_BGRA8888);
1444                 if ((err != MS_MEDIA_ERR_NONE) || (new_frame == NULL)) {
1445                         thumb_err("_media_thumb_convert_video falied: %d", err);
1446                         mm_file_destroy_content_attrs(content);
1447                         SAFE_FREE(new_frame);
1448                         return err;
1449                 }
1450                 mm_file_destroy_content_attrs(content);
1451                 thumb_dbg("original size - width:%d, height:%d", width, height);
1452                 thumb_dbg("proper thumb size - width:%d, height:%d", thumb_width, thumb_height);
1453                 if (width > thumb_width || height > thumb_height) {
1454                         err = _media_thumb_resize_video_with_evas(new_frame, thumb_width, thumb_height, thumb_info);
1455                         if (err != MS_MEDIA_ERR_NONE) {
1456                                 thumb_err("_media_thumb_resize_video_with_evas falied: %d", err);
1457                                 SAFE_FREE(new_frame);
1458                                 return err;
1459                         }
1460                 } else {
1461                         thumb_info->size = new_size;
1462                         thumb_info->width = width;
1463                         thumb_info->height = height;
1464                         thumb_info->data = malloc(new_size);
1465                         if (thumb_info->data == NULL) {
1466                                 thumb_err("memory allcation failed");
1467                                 SAFE_FREE(new_frame);
1468                                 return MS_MEDIA_ERR_OUT_OF_MEMORY;
1469                         }
1470                         memcpy(thumb_info->data, new_frame, new_size);
1471                 }
1472                 SAFE_FREE(new_frame);
1473
1474                 if (rot_type == MM_UTIL_ROTATE_90 || rot_type == MM_UTIL_ROTATE_180 || rot_type == MM_UTIL_ROTATE_270) {
1475                         err = _media_thumb_rotate_thumb(thumb_info->data, thumb_info->size, &(thumb_info->width), &(thumb_info->height), rot_type, MM_UTIL_JPEG_FMT_BGRA8888);
1476                         if (err != MS_MEDIA_ERR_NONE) {
1477                                 thumb_err("_media_thumb_rotate_thumb falied: %d", err);
1478                                 SAFE_FREE(thumb_info->data);
1479                                 return err;
1480                         }
1481                 }
1482 #else
1483                 if (width > thumb_width || height > thumb_height) {
1484                         err = _media_thumb_resize_data(frame,
1485                                                                                 width,
1486                                                                                 height,
1487                                                                                 MM_UTIL_IMG_FMT_RGB888,
1488                                                                                 thumb_info,
1489                                                                                 thumb_width,
1490                                                                                 thumb_height);
1491
1492                         if (err != MS_MEDIA_ERR_NONE) {
1493                                 thumb_err("_media_thumb_resize_data failed - %d", err);
1494                                 SAFE_FREE(thumb_info->data);
1495                                 mm_file_destroy_content_attrs(content);
1496                                 return err;
1497                         }
1498                 } else {
1499                         thumb_info->size = size;
1500                         thumb_info->width = width;
1501                         thumb_info->height = height;
1502                         thumb_info->data = malloc(size);
1503                         if (thumb_info->data == NULL) {
1504                                 thumb_err("memory allcation failed");
1505                                 mm_file_destroy_content_attrs(content);
1506                                 return MS_MEDIA_ERR_OUT_OF_MEMORY;
1507                         }
1508                         memcpy(thumb_info->data, frame, size);
1509                 }
1510
1511                 mm_file_destroy_content_attrs(content);
1512                 if (rot_type == MM_UTIL_ROTATE_90 || rot_type == MM_UTIL_ROTATE_180 || rot_type == MM_UTIL_ROTATE_270) {
1513                         /* Start to decode to rotate */
1514                         unsigned char *rotated = NULL;
1515                         unsigned int r_w = thumb_info->height;
1516                         unsigned int r_h = thumb_info->width;
1517                         unsigned int r_size = 0;
1518
1519                         if (rot_type == MM_UTIL_ROTATE_180) {
1520                                 r_w = thumb_info->width;
1521                                 r_h = thumb_info->height;
1522                         }
1523
1524                         err = mm_util_get_image_size(MM_UTIL_IMG_FMT_RGB888, r_w, r_h, &r_size);
1525                         if (err != FILEINFO_ERROR_NONE) {
1526                                 thumb_err("mm_util_get_image_size failed : %d", err);
1527                                 SAFE_FREE(thumb_info->data);
1528                                 return err;
1529                         }
1530
1531                         //thumb_dbg("Size of Rotated : %d", r_size);
1532                         rotated = (unsigned char *)malloc(r_size);
1533                         err = mm_util_rotate_image(thumb_info->data, thumb_info->width, thumb_info->height,
1534                                                                                 MM_UTIL_IMG_FMT_RGB888,
1535                                                                                 rotated, &r_w, &r_h,
1536                                                                                 rot_type);
1537
1538                         if (err != FILEINFO_ERROR_NONE) {
1539                                 thumb_err("mm_util_rotate_image failed : %d", err);
1540                                 SAFE_FREE(thumb_info->data);
1541                                 SAFE_FREE(rotated);
1542                                 return err;
1543                         } else {
1544                                 thumb_dbg("mm_util_rotate_image succeed");
1545                         }
1546
1547                         SAFE_FREE(thumb_info->data);
1548                         thumb_info->data = rotated;
1549                         thumb_info->size = r_size;
1550                         thumb_info->width = r_w;
1551                         thumb_info->height = r_h;
1552                 }
1553                 err = _media_thumb_convert_format(thumb_info, MEDIA_THUMB_RGB888, format);
1554                 if (err != MS_MEDIA_ERR_NONE) {
1555                         thumb_err("_media_thumb_convert_format falied: %d", err);
1556                         SAFE_FREE(thumb_info->data);
1557                         return err;
1558                 }
1559 #endif
1560         } else {
1561                 thumb_dbg("no contents information");
1562                 frame = NULL;
1563                 mm_file_destroy_content_attrs(content);
1564
1565                 return MS_MEDIA_ERR_INTERNAL;
1566         }
1567
1568         return err;
1569 }
1570
1571 static char* _media_thumb_mmc_get_path(uid_t uid)
1572 {
1573         int ret = 0;
1574         char *result_psswd = NULL;
1575         struct group *grpinfo = NULL;
1576         if (uid == getuid()) {
1577                 if (THUMB_MMC_PATH != NULL)
1578                         result_psswd = strndup(THUMB_MMC_PATH, strlen(THUMB_MMC_PATH));
1579                 grpinfo = getgrnam("users");
1580                 if (grpinfo == NULL) {
1581                         thumb_err("getgrnam(users) returns NULL !");
1582                         if (result_psswd)
1583                                 free(result_psswd);
1584                         return NULL;
1585                 }
1586         } else {
1587                 struct passwd *userinfo = getpwuid(uid);
1588                 if (userinfo == NULL) {
1589                         thumb_err("getpwuid(%d) returns NULL !", uid);
1590                         return NULL;
1591                 }
1592                 grpinfo = getgrnam("users");
1593                 if (grpinfo == NULL) {
1594                         thumb_err("getgrnam(users) returns NULL !");
1595                         return NULL;
1596                 }
1597                 // Compare git_t type and not group name
1598                 if (grpinfo->gr_gid != userinfo->pw_gid) {
1599                         thumb_err("UID [%d] does not belong to 'users' group!", uid);
1600                         return NULL;
1601                 }
1602                 ret = asprintf(&result_psswd, "%s/share/media/.thumb/mmc", userinfo->pw_dir);
1603                 if (ret == -1) {
1604                         thumb_err("asprintf failed");
1605                         return NULL;
1606                 }
1607         }
1608
1609         return result_psswd;
1610 }
1611
1612 static char* _media_thumb_phone_get_path(uid_t uid)
1613 {
1614         int ret = 0;
1615         char *result_psswd = NULL;
1616         struct group *grpinfo = NULL;
1617         if (uid == getuid()) {
1618                 if (THUMB_PHONE_PATH != NULL)
1619                         result_psswd = strndup(THUMB_PHONE_PATH, strlen(THUMB_PHONE_PATH));
1620                 grpinfo = getgrnam("users");
1621                 if (grpinfo == NULL) {
1622                         thumb_err("getgrnam(users) returns NULL !");
1623                         if (result_psswd)
1624                                 free(result_psswd);
1625                         return NULL;
1626                 }
1627         } else {
1628                 struct passwd *userinfo = getpwuid(uid);
1629                 if (userinfo == NULL) {
1630                         thumb_err("getpwuid(%d) returns NULL !", uid);
1631                         return NULL;
1632                 }
1633                 grpinfo = getgrnam("users");
1634                 if (grpinfo == NULL) {
1635                         thumb_err("getgrnam(users) returns NULL !");
1636                         return NULL;
1637                 }
1638                 // Compare git_t type and not group name
1639                 if (grpinfo->gr_gid != userinfo->pw_gid) {
1640                         thumb_err("UID [%d] does not belong to 'users' group!", uid);
1641                         return NULL;
1642                 }
1643                 ret = asprintf(&result_psswd, "%s/share/media/.thumb/phone", userinfo->pw_dir);
1644                 if (ret == -1) {
1645                         thumb_err("asprintf failed");
1646                         return NULL;
1647                 }
1648         }
1649
1650         return result_psswd;
1651 }
1652
1653 int _media_thumb_get_hash_name(const char *file_full_path,
1654                                  char *thumb_hash_path, size_t max_thumb_path, uid_t uid)
1655 {
1656         char *hash_name = NULL;
1657         /*char *thumb_dir = NULL;*/
1658         char file_ext[255] = { 0 };
1659         char *get_path = NULL;
1660         int ret_len = 0;
1661         media_thumb_store_type store_type = -1;
1662
1663         if (file_full_path == NULL || thumb_hash_path == NULL || max_thumb_path <= 0) {
1664                 thumb_err("file_full_path==NULL || thumb_hash_path == NULL || max_thumb_path <= 0");
1665                 return MS_MEDIA_ERR_INVALID_PARAMETER;
1666         }
1667
1668         _media_thumb_get_file_ext(file_full_path, file_ext, sizeof(file_ext));
1669
1670         store_type = _media_thumb_get_store_type_by_path(file_full_path);
1671         /*if (store_type == THUMB_PHONE) {
1672                 thumb_dir = _media_thumb_phone_get_path(uid);
1673         } else if (store_type == THUMB_MMC) {
1674                 thumb_dir = _media_thumb_mmc_get_path(uid);
1675         } else {
1676                 thumb_dir = _media_thumb_phone_get_path(uid);
1677         }*/
1678
1679         hash_name = _media_thumb_generate_hash_name(file_full_path);
1680         if (hash_name == NULL) {
1681                 thumb_err("_media_thumb_generate_hash_name fail");
1682                 return MS_MEDIA_ERR_INTERNAL;
1683         }
1684
1685         if (store_type == THUMB_PHONE) {
1686                 get_path = _media_thumb_phone_get_path(uid);
1687                 if (get_path != NULL)
1688                         ret_len = snprintf(thumb_hash_path, max_thumb_path - 1, "%s/.%s-%s.jpg", get_path, file_ext, hash_name);
1689         } else if (store_type == THUMB_MMC) {
1690                 get_path = _media_thumb_mmc_get_path(uid);
1691                 if (get_path != NULL)
1692                         ret_len = snprintf(thumb_hash_path, max_thumb_path - 1, "%s/.%s-%s.jpg", get_path, file_ext, hash_name);
1693         } else {
1694                 get_path = _media_thumb_phone_get_path(uid);
1695                 if (get_path != NULL)
1696                         ret_len = snprintf(thumb_hash_path, max_thumb_path - 1, "%s/.%s-%s.jpg", get_path, file_ext, hash_name);
1697         }
1698
1699         SAFE_FREE(get_path);
1700
1701         if ((ret_len < 0) || (ret_len > (int)max_thumb_path)) {
1702                 thumb_err("invalid hash path ret_len[%d]", ret_len);
1703                 return MS_MEDIA_ERR_INTERNAL;
1704         }
1705         //thumb_dbg("thumb hash : %s", thumb_hash_path);
1706
1707         return MS_MEDIA_ERR_NONE;
1708 }
1709
1710
1711 int _media_thumb_save_to_file_with_evas(unsigned char *data,
1712                                                                                         int w,
1713                                                                                         int h,
1714                                                                                         int alpha,
1715                                                                                         char *thumb_path)
1716 {
1717         Ecore_Evas *ee = ecore_evas_buffer_new(w, h);
1718         if (ee == NULL) {
1719                 thumb_err("ecore_evas_buffer_new failed");
1720                 return MS_MEDIA_ERR_INTERNAL;
1721         }
1722
1723         Evas *evas = ecore_evas_get(ee);
1724         if (evas == NULL) {
1725                 thumb_err("ecore_evas_get failed");
1726                 ecore_evas_free(ee);
1727                 return MS_MEDIA_ERR_INTERNAL;
1728         }
1729
1730         Evas_Object *img = NULL;
1731         img = evas_object_image_add(evas);
1732
1733         if (img == NULL) {
1734                 thumb_err("evas_object_image_add failed");
1735                 ecore_evas_free(ee);
1736                 return MS_MEDIA_ERR_INTERNAL;
1737         }
1738
1739         evas_object_image_colorspace_set(img, EVAS_COLORSPACE_ARGB8888);
1740         evas_object_image_size_set(img, w, h);
1741         evas_object_image_fill_set(img, 0, 0, w, h);
1742
1743         if (alpha) evas_object_image_alpha_set(img, 1);
1744
1745         evas_object_image_data_set(img, data);
1746         evas_object_image_data_update_add(img, 0, 0, w, h);
1747
1748         if (evas_object_image_save(img, thumb_path, NULL,       "quality=90 compress=1")) {
1749                 thumb_dbg("evas_object_image_save success");
1750                 ecore_evas_free(ee);
1751
1752                 return MS_MEDIA_ERR_NONE;
1753         } else {
1754                 thumb_err("evas_object_image_save failed");
1755                 ecore_evas_free(ee);
1756                 return MS_MEDIA_ERR_INTERNAL;
1757         }
1758 }