Fix socket bind bug.
[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_error.h>
42 #include <mm_util_imgp.h>
43 #include <mm_util_jpeg.h>
44 #include <libexif/exif-data.h>
45 #include <gdk-pixbuf/gdk-pixbuf.h>
46
47 #define MEDA_THUMB_ROUND_UP_4(num)  (((num)+3)&~3)
48
49 int _media_thumb_get_proper_thumb_size(media_thumb_type thumb_type,
50                                                                 int orig_w, int orig_h,
51                                                                 int *thumb_w, int *thumb_h)
52 {
53         thumb_dbg("orig w: %d orig h: %d thumb type: %d", orig_w, orig_h, thumb_type);
54
55         BOOL portrait = FALSE;
56         double ratio;
57
58         if (orig_w < orig_h) {
59                 portrait = TRUE;
60         }
61
62         /* Set smaller length to default size */
63         if (portrait) {
64                 if (orig_w < _media_thumb_get_width(thumb_type)) {
65                         *thumb_w = orig_w;
66                 } else {
67                         *thumb_w = _media_thumb_get_width(thumb_type);
68                 }
69
70                 ratio = (double)orig_h / (double)orig_w;
71                 *thumb_h = *thumb_w * ratio;
72
73         } else {
74
75                 if (orig_h < _media_thumb_get_width(thumb_type)) {
76                         *thumb_h = orig_h;
77                 } else {
78                         *thumb_h = _media_thumb_get_width(thumb_type);
79                 }
80
81                 ratio = (double)orig_w / (double)orig_h;
82                 *thumb_w = *thumb_h * ratio;
83         }
84
85         /* The width of RGB888 raw data has to be rounded by 4 */
86         *thumb_w = MEDA_THUMB_ROUND_UP_4(*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,
94                      int ifdtype, long tagtype)
95 {
96         ExifEntry *entry;
97         ExifIfd ifd;
98         ExifTag tag;
99
100         if (ed == NULL) {
101                 return MS_MEDIA_ERR_INVALID_PARAMETER;
102         }
103
104         ifd = ifdtype;
105         tag = tagtype;
106
107         entry = exif_content_get_entry(ed->ifd[ifd], tag);
108         if (entry) {
109                 if (tag == EXIF_TAG_ORIENTATION ||
110                                 tag == EXIF_TAG_PIXEL_X_DIMENSION ||
111                                 tag == EXIF_TAG_PIXEL_Y_DIMENSION) {
112
113                         if (value == NULL) {
114                                 thumb_err("value is NULL");
115                                 return MS_MEDIA_ERR_INVALID_PARAMETER;
116                         }
117
118                         ExifByteOrder mByteOrder = exif_data_get_byte_order(ed);
119                         short exif_value = exif_get_short(entry->data, mByteOrder);
120                         thumb_dbg("%s : %d", exif_tag_get_name_in_ifd(tag,ifd), exif_value);
121                         *value = (int)exif_value;
122                 } else {
123                         /* Get the contents of the tag in human-readable form */
124                         if (buf == NULL) {
125                                 thumb_err("buf is NULL");
126                                 return MS_MEDIA_ERR_INVALID_PARAMETER;
127                         }
128                         exif_entry_get_value(entry, buf, max_size);
129                         buf[strlen(buf)] = '\0';
130
131                         if (*buf) {
132                                 thumb_dbg("%s: %s\n", exif_tag_get_name_in_ifd(tag, ifd), buf);
133                         }
134                 }
135         }
136
137         return MS_MEDIA_ERR_NONE;
138 }
139
140 int _media_thumb_get_thumb_from_exif(ExifData *ed,
141                                                                 const char *file_full_path,
142                                                                 int orientation,
143                                                                 int required_width,
144                                                                 int required_height,
145                                                                 media_thumb_info *thumb_info, uid_t uid)
146 {
147         ExifEntry *entry;
148         ExifIfd ifd;
149         ExifTag tag;
150
151         int err = -1;
152         int size = 0;
153         int thumb_width = 0;
154         int thumb_height = 0;
155         void *thumb = NULL;
156
157         if (ed == NULL) {
158                 return -1;
159         }
160
161         ExifByteOrder byte_order = exif_data_get_byte_order(ed);
162
163         ifd = EXIF_IFD_1;
164         tag = EXIF_TAG_COMPRESSION;
165
166         entry = exif_content_get_entry(ed->ifd[ifd], tag);
167
168         if (entry) {
169                 /* Get the contents of the tag in human-readable form */
170                 ExifShort value = exif_get_short(entry->data, byte_order);
171                 //thumb_dbg("%s: %d", exif_tag_get_name_in_ifd(tag,ifd), value);
172
173                 if (value == 6) {
174                         thumb_dbg("There's jpeg thumb in this image");
175                 } else {
176                         thumb_dbg("There's NO jpeg thumb in this image");
177                         return MS_MEDIA_ERR_INVALID_PARAMETER;
178                 }
179         } else {
180                 thumb_dbg("entry is NULL");
181                 return MS_MEDIA_ERR_INVALID_PARAMETER;
182         }
183
184         /* Get width and height of thumbnail */
185         tag = EXIF_TAG_IMAGE_WIDTH;
186         entry = exif_content_get_entry(ed->ifd[ifd], tag);
187
188         if (entry) {
189                 /* Get the contents of the tag in human-readable form */
190                 ExifShort value = exif_get_short(entry->data, byte_order);
191                 //thumb_dbg("%s: %d\n", exif_tag_get_name_in_ifd(tag,ifd), value);
192
193                 thumb_width = value;
194         }
195
196         tag = EXIF_TAG_IMAGE_LENGTH;
197         entry = exif_content_get_entry(ed->ifd[ifd], tag);
198         if (entry) {
199                 /* Get the contents of the tag in human-readable form */
200                 ExifShort value = exif_get_short(entry->data, byte_order);
201                 //thumb_dbg("%s: %d\n", exif_tag_get_name_in_ifd(tag,ifd), value);
202
203                 thumb_height = value;
204         }
205
206         if (ed->data && ed->size) {
207                 //thumb_dbg("Size: %d, thumb: 0x%x\n", ed->size, ed->data);
208                 thumb = (char *)malloc(ed->size);
209
210                 if (thumb == NULL) { 
211                         thumb_dbg("malloc failed!");
212                         return -1;
213                 }
214
215                 memcpy(thumb, (void *)ed->data, ed->size);
216                 size = ed->size;
217         } else {
218                 thumb_dbg("data is NULL");
219                 return -1;
220         }
221
222         /* Get width and height of original image from exif */
223         ifd = EXIF_IFD_EXIF;
224         tag = EXIF_TAG_PIXEL_X_DIMENSION;
225         entry = exif_content_get_entry(ed->ifd[ifd], tag);
226
227         if (entry) {
228                 ExifShort value = exif_get_short(entry->data, byte_order);
229                 //thumb_dbg("%s: %d\n", exif_tag_get_name_in_ifd(tag,ifd), value);
230                 thumb_info->origin_width = value;
231         } else {
232                 thumb_dbg("entry is NULL");
233         }
234
235         tag = EXIF_TAG_PIXEL_Y_DIMENSION;
236         entry = exif_content_get_entry(ed->ifd[ifd], tag);
237
238         if (entry) {
239                 ExifShort value = exif_get_short(entry->data, byte_order);
240                 //thumb_dbg("%s: %d\n", exif_tag_get_name_in_ifd(tag,ifd), value);
241                 thumb_info->origin_height = value;
242         } else {
243                 thumb_dbg("entry is NULL");
244         }
245
246         char thumb_path[1024];
247
248         err =
249             _media_thumb_get_hash_name(file_full_path,
250                                              thumb_path,
251                                              sizeof(thumb_path), uid);
252         if (err < 0) {
253                 thumb_dbg("_media_thumb_get_hash_name failed\n");
254                 SAFE_FREE(thumb);
255                 return err;
256         }
257
258         thumb_dbg("Thumb is :%s", thumb_path);
259
260         int nwrite;
261         int fd = open(thumb_path, O_RDWR | O_CREAT | O_EXCL | O_SYNC, 0644);
262         if (fd < 0) {
263                 if (errno == EEXIST) {
264                         thumb_dbg("thumb alread exist!");
265                 } else {
266                         thumb_dbg("open failed\n");
267                         SAFE_FREE(thumb);
268                         return -1;
269                 }
270         } else {
271                 nwrite = write(fd, thumb, size);
272                 if (nwrite < 0) {
273                         thumb_dbg("write failed\n");
274                         close(fd);
275         
276                         SAFE_FREE(thumb);
277                         return -1;
278                 }
279                 close(fd);
280         }
281
282         SAFE_FREE(thumb);
283
284         mm_util_jpeg_yuv_data decoded = {0,};
285
286         err = mm_util_decode_from_jpeg_file(&decoded, thumb_path, MM_UTIL_JPEG_FMT_RGB888);
287         if (err < 0) {
288                 thumb_dbg("mm_util_decode_from_jpeg_turbo_memory failed : %d", err);
289                 return err;
290         }
291
292         //thumb_dbg("size:%d, w:%d, h:%d\n", decoded.size, decoded.width, decoded.height);
293
294         thumb_width = decoded.width;
295         thumb_height = decoded.height;
296
297         media_thumb_type thumb_type;
298         int need_resize = 0;
299         unsigned int buf_size = decoded.size;
300
301         if (required_width == _media_thumb_get_width(MEDIA_THUMB_LARGE)) {
302                 thumb_type = MEDIA_THUMB_LARGE;
303         } else {
304                 thumb_type = MEDIA_THUMB_SMALL;
305         }
306
307         if (thumb_type == MEDIA_THUMB_LARGE) {
308                 if (thumb_width < _media_thumb_get_width(MEDIA_THUMB_LARGE)) {
309                         thumb_dbg("Thumb data in exif is too small for MEDIA_THUMB_LARGE");
310                         SAFE_FREE(decoded.data);
311                         return -1;
312                 }
313         } else {
314                 if (thumb_width > _media_thumb_get_width(MEDIA_THUMB_SMALL)) {
315                         need_resize = 1;
316                 }
317         }
318
319         if (need_resize == 1) {
320                 int resized_w = _media_thumb_get_width(MEDIA_THUMB_LARGE);
321                 int resized_h = _media_thumb_get_height(MEDIA_THUMB_LARGE);
322
323                 err = mm_util_get_image_size(MM_UTIL_IMG_FMT_RGB888, resized_w, resized_h, &buf_size);
324                 if (err < 0) {
325                         thumb_dbg("mm_util_get_image_size failed : %d", err);
326
327                         SAFE_FREE(decoded.data);
328                         return err;
329                 }
330
331                 //thumb_dbg("size(RGB888) : %d", buf_size);
332
333                 unsigned char *dst = (unsigned char *)malloc(buf_size);
334                 if (dst == NULL) {
335                         thumb_err("Failed to allocate memory!");
336                         SAFE_FREE(decoded.data);
337                         return -1;
338                 }
339
340                 if (mm_util_resize_image(decoded.data, thumb_width,
341                                 thumb_height, MM_UTIL_IMG_FMT_RGB888,
342                                 dst, (unsigned int *)&resized_w,
343                                 (unsigned int *)&resized_h) < 0) {
344                         thumb_err("Failed to resize the thumbnails");
345
346                         SAFE_FREE(decoded.data);
347                         SAFE_FREE(dst);
348
349                         return -1;
350                 }
351
352                 SAFE_FREE(decoded.data);
353                 decoded.data = dst;
354                 decoded.width = thumb_width = resized_w;
355                 decoded.height = thumb_height = resized_h;
356         }
357
358         if (orientation == ROT_90 || orientation == ROT_180 || orientation == ROT_270) {
359                 /* Start to decode to rotate */
360                 unsigned char *rotated = NULL;
361                 unsigned int r_w = decoded.height;
362                 unsigned int r_h = decoded.width;
363                 unsigned int r_size = 0;
364                 mm_util_img_rotate_type rot_type = MM_UTIL_ROTATE_0;
365
366                 if (orientation == ROT_90) {
367                         rot_type = MM_UTIL_ROTATE_90;
368                 } else if (orientation == ROT_180) {
369                         rot_type = MM_UTIL_ROTATE_180;
370                         r_w = decoded.width;
371                         r_h = decoded.height;
372                 } else if (orientation == ROT_270) {
373                         rot_type = MM_UTIL_ROTATE_270;
374                 }
375
376                 err = mm_util_get_image_size(MM_UTIL_IMG_FMT_RGB888, r_w, r_h, &r_size);
377                 if (err < 0) {
378                         thumb_dbg("mm_util_get_image_size failed : %d", err);
379                         SAFE_FREE(decoded.data);
380                         return err;
381                 }
382
383                 //thumb_dbg("Size of Rotated : %d", r_size);
384
385                 rotated = (unsigned char *)malloc(r_size);
386                 err = mm_util_rotate_image(decoded.data, decoded.width, decoded.height, 
387                                                                         MM_UTIL_IMG_FMT_RGB888,
388                                                                         rotated, &r_w, &r_h, 
389                                                                         rot_type);
390         
391                 if (err < 0) {
392                         thumb_err("mm_util_rotate_image failed : %d", err);
393                         SAFE_FREE(decoded.data);
394                         SAFE_FREE(rotated);
395                         return err;
396                 } else {
397                         thumb_dbg("mm_util_rotate_image succeed");
398                 }
399
400                 SAFE_FREE(decoded.data);
401
402                 //thumb_dbg("Width : %d, Height : %d", r_w, r_h);
403                 thumb_info->data = rotated;
404                 thumb_info->size = r_size;
405                 thumb_info->width = r_w;
406                 thumb_info->height = r_h;
407         } else if (orientation == NORMAL) {
408                 thumb_info->data = decoded.data;
409                 thumb_info->size = buf_size;
410                 thumb_info->width = thumb_width;
411                 thumb_info->height = thumb_height;
412         } else {
413                 thumb_warn("Unknown orientation");
414                 SAFE_FREE(decoded.data);
415                 return -1;
416         }
417
418         return 0;
419 }
420
421 int _media_thumb_resize_data(unsigned char *src_data,
422                                                         int src_width,
423                                                         int src_height,
424                                                         mm_util_img_format src_format,
425                                                         media_thumb_info *thumb_info,
426                                                         int dst_width,
427                                                         int dst_height)
428 {
429         int thumb_width = dst_width;
430         int thumb_height = dst_height;
431         unsigned int buf_size = 0;
432
433         if (mm_util_get_image_size(src_format, thumb_width, thumb_height, &buf_size) < 0) {
434                 thumb_err("Failed to get buffer size");
435                 return MS_MEDIA_ERR_INTERNAL;
436         }
437
438         thumb_dbg("mm_util_get_image_size : %d", buf_size);
439
440         unsigned char *dst = (unsigned char *)malloc(buf_size);
441
442         if (mm_util_resize_image((unsigned char *)src_data, src_width,
443                         src_height, src_format,
444                         dst, (unsigned int *)&thumb_width,
445                         (unsigned int *)&thumb_height) < 0) {
446                 thumb_err("Failed to resize the thumbnails");
447
448                 SAFE_FREE(dst);
449
450                 return MS_MEDIA_ERR_INTERNAL;
451         }
452
453         thumb_info->size = buf_size;
454         thumb_info->width = thumb_width;
455         thumb_info->height = thumb_height;
456         thumb_info->data = malloc(buf_size);
457         memcpy(thumb_info->data, dst, buf_size);
458
459         SAFE_FREE(dst);
460
461         return MS_MEDIA_ERR_NONE;
462 }
463
464 int _media_thumb_get_wh_with_gdk(const char *origin_path, int *width, int *height)
465 {
466
467         GdkPixbuf *pixbuf = NULL;
468         GError *error = NULL;
469
470         pixbuf = gdk_pixbuf_new_from_file(origin_path, &error);
471         if (error) {
472                 thumb_err ("Error loading image file %s",origin_path);
473                 g_error_free (error);
474                 return MS_MEDIA_ERR_INTERNAL;
475         }
476
477         /* Get w/h of original image */
478         *width = gdk_pixbuf_get_width(pixbuf);
479         *height = gdk_pixbuf_get_height(pixbuf);
480
481         return MS_MEDIA_ERR_NONE;
482 }
483
484 int _media_thumb_decode_with_gdk(const char *origin_path,
485                                         int thumb_width, int thumb_height,
486                                         media_thumb_info *thumb_info, int need_scale, int orientation)
487 {
488         GdkPixbuf *pixbuf = NULL;
489         GError *error = NULL;
490
491         pixbuf = gdk_pixbuf_new_from_file(origin_path, &error);
492         if (error) {
493                 thumb_err ("Error loading image file %s",origin_path);
494                 g_error_free (error);
495                 return MS_MEDIA_ERR_INTERNAL;
496         }
497
498         /* Get w/h of original image */
499         int width = gdk_pixbuf_get_width(pixbuf);
500         int height = gdk_pixbuf_get_height(pixbuf);
501
502         thumb_info->origin_width = width;
503         thumb_info->origin_height = height;
504
505
506         pixbuf = gdk_pixbuf_apply_embedded_orientation(pixbuf);
507
508         int rotated_orig_w = 0;
509         int rotated_orig_h = 0;
510
511         if (orientation == ROT_90 || orientation == ROT_270) {
512                 rotated_orig_w = height;
513                 rotated_orig_h = width;
514         } else {
515                 rotated_orig_w = width;
516                 rotated_orig_h = height;
517         }
518
519         int err = MS_MEDIA_ERR_NONE;
520         media_thumb_type thumb_type;
521
522         if (thumb_width == _media_thumb_get_width(MEDIA_THUMB_LARGE)) {
523                 thumb_type = MEDIA_THUMB_LARGE;
524         } else {
525                 thumb_type = MEDIA_THUMB_SMALL;
526         }
527
528         err = _media_thumb_get_proper_thumb_size(thumb_type,
529                                                                         rotated_orig_w, rotated_orig_h,
530                                                                         &thumb_width, &thumb_height);
531         if (err != MS_MEDIA_ERR_NONE) {
532                 thumb_err("_media_thumb_get_proper_thumb_size failed: %d", err);
533                 g_object_unref(pixbuf);
534                 return err;
535         }
536
537         pixbuf = gdk_pixbuf_scale_simple(pixbuf, thumb_width, thumb_height, GDK_INTERP_NEAREST);
538
539         unsigned int buf_size = 0;
540
541         if (mm_util_get_image_size(MM_UTIL_IMG_FMT_BGRA8888, thumb_width,
542                         thumb_height, &buf_size) < 0) {
543                 thumb_err("Failed to get buffer size");
544
545                 g_object_unref(pixbuf);
546
547                 return MS_MEDIA_ERR_INTERNAL;
548         }
549
550         thumb_info->size = buf_size;
551         thumb_info->alpha = gdk_pixbuf_get_has_alpha(pixbuf);
552         thumb_info->width = thumb_width;
553         thumb_info->height = thumb_height;
554         thumb_info->gdkdata = gdk_pixbuf_copy(pixbuf);
555
556         g_object_unref(pixbuf);
557         return MS_MEDIA_ERR_NONE;
558 }
559
560 mm_util_img_format _media_thumb_get_format(media_thumb_format src_format)
561 {
562         switch(src_format) {
563                 case MEDIA_THUMB_BGRA:
564                         return MM_UTIL_IMG_FMT_BGRA8888;
565                 case MEDIA_THUMB_RGB888:
566                         return MM_UTIL_IMG_FMT_RGB888;
567                 default:
568                         return MS_MEDIA_ERR_INVALID_PARAMETER;
569         }
570 }
571
572 int _media_thumb_convert_data(media_thumb_info *thumb_info,
573                                                         int thumb_width,
574                                                         int thumb_height,
575                                                         mm_util_img_format src_format,
576                                                         mm_util_img_format dst_format)
577 {
578         int err = MS_MEDIA_ERR_NONE;
579         unsigned int buf_size = 0;
580         unsigned char *src_data = thumb_info->data;
581         unsigned char *dst_data = NULL;
582
583         thumb_dbg("src format:%d, dst format:%d", src_format, dst_format);
584
585         if (mm_util_get_image_size(dst_format, thumb_width, thumb_height, &buf_size) < 0) {
586                 thumb_err("Failed to get buffer size");
587                 return MS_MEDIA_ERR_INTERNAL;
588         }
589
590         thumb_dbg("mm_util_get_image_size : %d", buf_size);
591
592         dst_data = (unsigned char *)malloc(buf_size);
593
594         if (src_format == MM_UTIL_IMG_FMT_RGB888 &&
595                 dst_format == MM_UTIL_IMG_FMT_BGRA8888) {
596
597                 int i = 0, j;
598                 for (j = 0; j < thumb_width * 3 * thumb_height;
599                                 j += 3) {
600                         dst_data[i++] = (src_data[j + 2]);
601                         dst_data[i++] = (src_data[j + 1]);
602                         dst_data[i++] = (src_data[j]);
603                         dst_data[i++] = 0x0;
604                 }
605
606         } else {
607                 err = mm_util_convert_colorspace(src_data,
608                                                 thumb_width,
609                                                 thumb_height,
610                                                 src_format,
611                                                 dst_data,
612                                                 dst_format);
613
614                 if (err < 0) {
615                         thumb_err("Failed to change from rgb888 to argb8888 %d", err);
616                         SAFE_FREE(dst_data);
617                         return MS_MEDIA_ERR_INTERNAL;
618                 }
619         }
620
621         SAFE_FREE(thumb_info->data);
622         thumb_info->data = dst_data;
623         thumb_info->size = buf_size;
624
625         thumb_dbg("_media_thumb_convert_data success");
626
627         return err;
628 }
629
630 int _media_thumb_convert_format(media_thumb_info *thumb_info,
631                                                         media_thumb_format src_format,
632                                                         media_thumb_format dst_format)
633 {
634         int err = MS_MEDIA_ERR_NONE;
635
636         if (src_format == dst_format) {
637                 //thumb_dbg("src_format == dst_format");
638                 return err;
639         }
640
641         mm_util_img_format src_mm_format;
642         mm_util_img_format dst_mm_format;
643
644         src_mm_format = _media_thumb_get_format(src_format);
645         dst_mm_format = _media_thumb_get_format(dst_format);
646
647         if (src_mm_format == -1 || dst_mm_format == -1) {
648                 thumb_err("Format is invalid");
649                 return MS_MEDIA_ERR_INVALID_PARAMETER;
650         }
651
652         err = _media_thumb_convert_data(thumb_info,
653                                         thumb_info->width,
654                                         thumb_info->height,
655                                         src_mm_format,
656                                         dst_mm_format);
657
658         if (err != MS_MEDIA_ERR_NONE) {
659                 thumb_err("media_thumb_convert_format failed : %d", err);
660                 return err;
661         }
662
663         return err;
664 }
665
666 int _media_thumb_agif(const char *origin_path,
667                                         ImgImageInfo *image_info,
668                                         int thumb_width,
669                                         int thumb_height,
670                                         media_thumb_format format,
671                                         media_thumb_info *thumb_info)
672 {
673         int err = MS_MEDIA_ERR_NONE;
674         unsigned int *thumb = NULL;
675         media_thumb_type thumb_type;
676
677         thumb = ImgGetFirstFrameAGIFAtSize(origin_path, image_info);
678
679         if (!thumb) {
680                 thumb_err("Frame data is NULL!!");
681                 return MS_MEDIA_ERR_INTERNAL;
682         }
683
684         if (thumb_width == _media_thumb_get_width(MEDIA_THUMB_LARGE)) {
685                 thumb_type = MEDIA_THUMB_LARGE;
686         } else {
687                 thumb_type = MEDIA_THUMB_SMALL;
688         }
689
690         err = _media_thumb_get_proper_thumb_size(thumb_type,
691                                                                         thumb_info->origin_width, thumb_info->origin_height,
692                                                                         &thumb_width, &thumb_height);
693         if (err != MS_MEDIA_ERR_NONE) {
694                 thumb_err("_media_thumb_get_proper_thumb_size failed: %d", err);
695                 SAFE_FREE(thumb);
696                 return err;
697         }
698
699         err = _media_thumb_resize_data((unsigned char *)thumb,
700                                                                         image_info->width,
701                                                                         image_info->height,
702                                                                         MM_UTIL_IMG_FMT_RGB888,
703                                                                         thumb_info,
704                                                                         thumb_width,
705                                                                         thumb_height);
706
707         if (err != MS_MEDIA_ERR_NONE) {
708                 thumb_err("_media_thumb_resize_data failed: %d", err);
709                 SAFE_FREE(thumb);
710                 return err;
711         }
712
713         SAFE_FREE(thumb);
714
715         err = _media_thumb_convert_format(thumb_info, MEDIA_THUMB_RGB888, format);
716         if (err != MS_MEDIA_ERR_NONE) {
717                 thumb_err("_media_thumb_convert_format falied: %d", err);
718                 SAFE_FREE(thumb_info->data);
719                 return err;
720         }
721
722         return err;
723 }
724
725 int _media_thumb_png(const char *origin_path,
726                                         int thumb_width,
727                                         int thumb_height,
728                                         media_thumb_format format,
729                                         media_thumb_info *thumb_info)
730 {
731         int err = MS_MEDIA_ERR_NONE;
732         err = _media_thumb_decode_with_gdk(origin_path, thumb_width, thumb_height, thumb_info, 0, NORMAL);
733
734         if (err != MS_MEDIA_ERR_NONE) {
735                 thumb_err("decode_with_gdk failed : %d", err);
736                 return err;
737         }
738
739         err = _media_thumb_convert_format(thumb_info, MEDIA_THUMB_RGB888, format);
740         if (err != MS_MEDIA_ERR_NONE) {
741                 thumb_err("_media_thumb_convert_format falied: %d", err);
742                 SAFE_FREE(thumb_info->data);
743                 return err;
744         }
745
746         return err;
747 }
748
749 int _media_thumb_bmp(const char *origin_path,
750                                         int thumb_width,
751                                         int thumb_height,
752                                         media_thumb_format format,
753                                         media_thumb_info *thumb_info)
754 {
755         int err = MS_MEDIA_ERR_NONE;
756         err = _media_thumb_decode_with_gdk(origin_path, thumb_width, thumb_height, thumb_info, 0, NORMAL);
757
758         if (err != MS_MEDIA_ERR_NONE) {
759                 thumb_err("decode_with_gdk failed : %d", err);
760                 return err;
761         }
762
763         err = _media_thumb_convert_format(thumb_info, MEDIA_THUMB_RGB888, format);
764         if (err != MS_MEDIA_ERR_NONE) {
765                 thumb_err("_media_thumb_convert_format falied: %d", err);
766                 SAFE_FREE(thumb_info->data);
767                 return err;
768         }
769
770         return err;
771 }
772
773 int _media_thumb_wbmp(const char *origin_path,
774                                         int thumb_width,
775                                         int thumb_height,
776                                         media_thumb_format format,
777                                         media_thumb_info *thumb_info)
778 {
779         int err = MS_MEDIA_ERR_NONE;
780         err = _media_thumb_decode_with_gdk(origin_path, thumb_width, thumb_height, thumb_info, 0, NORMAL);
781
782         if (err != MS_MEDIA_ERR_NONE) {
783                 thumb_err("decode_with_gdk failed : %d", err);
784                 return err;
785         }
786
787         err = _media_thumb_convert_format(thumb_info, MEDIA_THUMB_RGB888, format);
788         if (err != MS_MEDIA_ERR_NONE) {
789                 thumb_err("_media_thumb_convert_format falied: %d", err);
790                 SAFE_FREE(thumb_info->data);
791                 return err;
792         }
793
794         return err;
795 }
796
797 int _media_thumb_gif(const char *origin_path,
798                                         int thumb_width,
799                                         int thumb_height,
800                                         media_thumb_format format,
801                                         media_thumb_info *thumb_info)
802 {
803         int err = MS_MEDIA_ERR_NONE;
804         err = _media_thumb_decode_with_gdk(origin_path, thumb_width, thumb_height, thumb_info, 0, NORMAL);
805
806         if (err != MS_MEDIA_ERR_NONE) {
807                 thumb_err("decode_with_gdk failed : %d", err);
808                 return err;
809         }
810
811         err = _media_thumb_convert_format(thumb_info, MEDIA_THUMB_RGB888, format);
812         if (err != MS_MEDIA_ERR_NONE) {
813                 thumb_err("_media_thumb_convert_format falied: %d", err);
814                 SAFE_FREE(thumb_info->data);
815                 return err;
816         }
817
818         return err;
819 }
820
821 int _media_thumb_jpeg(const char *origin_path,
822                                         int thumb_width,
823                                         int thumb_height,
824                                         media_thumb_format format,
825                                         media_thumb_info *thumb_info,
826                                         uid_t uid)
827 {
828         int err = MS_MEDIA_ERR_NONE;
829         ExifData *ed = NULL;
830         int thumb_done = 0;
831         int orientation = NORMAL;
832
833         /* Load an ExifData object from an EXIF file */
834         ed = exif_data_new_from_file(origin_path);
835
836         if (ed) {
837                 /* First, Get orientation from exif */
838                 err = _media_thumb_get_exif_info(ed, NULL, 0, &orientation, EXIF_IFD_0, EXIF_TAG_ORIENTATION);
839
840                 if (err != MS_MEDIA_ERR_NONE) {
841                         thumb_warn("_media_thumb_get_exif_info failed");
842                 }
843
844                 /* Second, Get thumb from exif */
845                 err = _media_thumb_get_thumb_from_exif(ed, origin_path, orientation, thumb_width, thumb_height, thumb_info, uid);
846
847                 if (err != MS_MEDIA_ERR_NONE) {
848                         thumb_dbg("_media_thumb_get_thumb_from_exif failed");
849                 } else {
850                         thumb_done = 1;
851                         thumb_dbg("_media_thumb_get_thumb_from_exif succeed");
852
853                         mm_util_img_format dst_format = _media_thumb_get_format(format);
854
855                         err = _media_thumb_convert_data(thumb_info, 
856                                                         thumb_info->width, 
857                                                         thumb_info->height,
858                                                         MM_UTIL_IMG_FMT_RGB888,
859                                                         dst_format);
860
861                         if (err != MS_MEDIA_ERR_NONE) {
862                                 thumb_err("_media_thumb_convert_data failed : %d", err);
863                                 exif_data_unref(ed);
864                                 return err;
865                         }
866                 }
867
868                 exif_data_unref(ed);
869         }
870
871         if (!thumb_done) {
872
873                 err = _media_thumb_decode_with_gdk(origin_path, thumb_width, thumb_height, thumb_info, 0, orientation);
874
875                 if (err != MS_MEDIA_ERR_NONE) {
876                         thumb_err("decode_with_gdk failed : %d", err);
877                         return err;
878                 }
879
880                 err = _media_thumb_convert_format(thumb_info, MEDIA_THUMB_RGB888, format);
881                 if (err != MS_MEDIA_ERR_NONE) {
882                         thumb_err("_media_thumb_convert_format falied: %d", err);
883                         SAFE_FREE(thumb_info->data);
884                         return err;
885                 }
886         }
887
888         return err;
889 }
890
891 int _media_thumb_jpeg_for_raw(const char *origin_path,
892                                         int thumb_width,
893                                         int thumb_height,
894                                         media_thumb_format format,
895                                         media_thumb_info *thumb_info,
896                                         uid_t uid)
897 {
898         int err = MS_MEDIA_ERR_NONE;
899         int orientation = NORMAL;
900
901         err = _media_thumb_decode_with_gdk(origin_path, thumb_width, thumb_height, thumb_info, 0, orientation);
902
903         if (err != MS_MEDIA_ERR_NONE) {
904                 thumb_err("decode_with_gdk failed : %d", err);
905                 return err;
906         }
907         /* Temporary process */
908         thumb_info->data = gdk_pixbuf_get_pixels(thumb_info->gdkdata);
909
910         err = _media_thumb_convert_format(thumb_info, MEDIA_THUMB_RGB888, format);
911         if (err != MS_MEDIA_ERR_NONE) {
912                 thumb_err("_media_thumb_convert_format falied: %d", err);
913                 SAFE_FREE(thumb_info->data);
914                 return err;
915         }
916         return err;
917 }
918
919 int _media_thumb_image(const char *origin_path,
920                                         int thumb_width,
921                                         int thumb_height,
922                                         media_thumb_format format,
923                                         media_thumb_info *thumb_info, 
924                                         bool is_raw,
925                                         uid_t uid)
926 {
927         int err = MS_MEDIA_ERR_NONE;
928         int image_type = 0;
929         int origin_w = 0;
930         int origin_h = 0;
931         ImgImageInfo image_info = { 0 };
932
933         image_type = ImgGetInfoFile(origin_path, &image_info);
934
935         thumb_info->origin_width = origin_w = image_info.width;
936         thumb_info->origin_height = origin_h = image_info.height;
937
938         thumb_dbg("image type is %d\n", image_type);
939
940         if ((image_type != IMG_CODEC_JPEG) &&
941                 (origin_w * origin_h > THUMB_MAX_ALLOWED_MEM_FOR_THUMB)) {
942                 thumb_warn("This original image is too big");
943                 return MS_MEDIA_ERR_THUMB_TOO_BIG;
944         }
945
946         if (image_type == IMG_CODEC_AGIF) {
947                 err = _media_thumb_agif(origin_path, &image_info, thumb_width, thumb_height, format, thumb_info);
948         } else if (image_type == IMG_CODEC_JPEG) {
949                 if(is_raw) {
950                         err = _media_thumb_jpeg_for_raw(origin_path, thumb_width, thumb_height, format, thumb_info, uid);
951                 } else {
952                         err = _media_thumb_jpeg(origin_path, thumb_width, thumb_height, format, thumb_info, uid);
953                 }
954         } else if (image_type == IMG_CODEC_PNG) {
955                 err = _media_thumb_png(origin_path, thumb_width, thumb_height, format, thumb_info);
956         } else if (image_type == IMG_CODEC_GIF) {
957                 err = _media_thumb_gif(origin_path, thumb_width, thumb_height, format, thumb_info);
958         } else if (image_type == IMG_CODEC_BMP) {
959                 err = _media_thumb_bmp(origin_path, thumb_width, thumb_height, format, thumb_info);
960         } else {
961                 char file_ext[10];
962                 err = _media_thumb_get_file_ext(origin_path, file_ext, sizeof(file_ext));
963                 if (err != MS_MEDIA_ERR_NONE) {
964                         thumb_warn("_media_thumb_get_file_ext failed");
965                 } else {
966                         if (strcasecmp(file_ext, "wbmp") == 0) {
967                                 image_type = IMG_CODEC_WBMP;
968                                 int wbmp_width = 0;
969                                 int wbmp_height = 0;
970
971                                 err = _media_thumb_get_wh_with_gdk(origin_path, &wbmp_width, &wbmp_height);
972                                 if (err != MS_MEDIA_ERR_NONE) {
973                                         thumb_err("_media_thumb_get_wh_with_gdk in WBMP : %d", err);
974                                         return err;
975                                 }
976
977                                 if (wbmp_width * wbmp_height > THUMB_MAX_ALLOWED_MEM_FOR_THUMB) {
978                                         thumb_warn("This original image is too big");
979                                         return MS_MEDIA_ERR_THUMB_TOO_BIG;
980                                 }
981
982                                 thumb_info->origin_width = wbmp_width;
983                                 thumb_info->origin_height = wbmp_height;
984
985                                 err = _media_thumb_wbmp(origin_path, thumb_width, thumb_height, format, thumb_info);
986
987                                 return err;
988                         }
989                 }
990
991                 thumb_warn("Unsupported image type");
992                 return MS_MEDIA_ERR_INVALID_PARAMETER;
993         }
994
995         return err;
996 }
997
998 int _media_thumb_video(const char *origin_path,
999                                         int thumb_width,
1000                                         int thumb_height,
1001                                         media_thumb_format format,
1002                                         media_thumb_info *thumb_info,
1003                                         uid_t uid)
1004 {
1005         int err = MS_MEDIA_ERR_NONE;
1006
1007         MMHandleType content = (MMHandleType) NULL;
1008         void *frame = NULL;
1009         int video_track_num = 0;
1010         char *err_msg = NULL;
1011         int is_drm = 0;
1012         int size = 0;
1013         int width = 0;
1014         int height = 0;
1015         GdkPixbuf *pixbuf;
1016         bool drm_type = FALSE;
1017
1018         is_drm = drm_type;
1019         err = mm_file_create_content_attrs(&content, origin_path);
1020
1021         if (err != MM_ERROR_NONE) {
1022                 thumb_err("mm_file_create_content_attrs fails : %d", err);
1023                 return MS_MEDIA_ERR_INTERNAL;
1024         }
1025
1026         err = mm_file_get_attrs(content, &err_msg, MM_FILE_CONTENT_VIDEO_TRACK_COUNT, &video_track_num, NULL);
1027         if (err != MM_ERROR_NONE) {
1028                 thumb_err("mm_file_get_attrs fails : %s", err_msg);
1029                 SAFE_FREE(err_msg);
1030                 mm_file_destroy_content_attrs(content);
1031                 return MS_MEDIA_ERR_INTERNAL;
1032         }
1033
1034         /* MMF api handle both normal and DRM video */
1035         if (video_track_num > 0 || is_drm) {
1036
1037                 err = mm_file_get_attrs(content, &err_msg,
1038                                         MM_FILE_CONTENT_VIDEO_WIDTH,
1039                                         &width,
1040                                         MM_FILE_CONTENT_VIDEO_HEIGHT,
1041                                         &height,
1042                                         MM_FILE_CONTENT_VIDEO_THUMBNAIL, &frame, /* raw image is RGB888 format */
1043                                         &size, NULL);
1044
1045                 if (err != MM_ERROR_NONE) {
1046                         thumb_err("mm_file_get_attrs fails : %s", err_msg);
1047                         SAFE_FREE(err_msg);
1048                         mm_file_destroy_content_attrs(content);
1049                         return MS_MEDIA_ERR_INTERNAL;
1050                 }
1051
1052                 thumb_dbg("video width: %d", width);
1053                 thumb_dbg("video height: %d", height);
1054                 thumb_dbg("thumbnail size=%d", size);
1055                 thumb_dbg("frame = 0x%x", frame);
1056
1057                 if (frame == NULL || width == 0 || height == 0) {
1058                         thumb_err("Failed to get frame data");
1059                         mm_file_destroy_content_attrs(content);
1060                         return MS_MEDIA_ERR_INTERNAL;
1061                 }
1062
1063                 media_thumb_type thumb_type;
1064                 if (thumb_width == _media_thumb_get_width(MEDIA_THUMB_LARGE)) {
1065                         thumb_type = MEDIA_THUMB_LARGE;
1066                 } else {
1067                         thumb_type = MEDIA_THUMB_SMALL;
1068                 }
1069
1070                 thumb_info->origin_width = width;
1071                 thumb_info->origin_height = height;
1072
1073                 err = _media_thumb_get_proper_thumb_size(thumb_type, width, height, &thumb_width, &thumb_height);
1074
1075                 if (width > thumb_width || height > thumb_height) {
1076                         err = _media_thumb_resize_data(frame,
1077                                                                                 width,
1078                                                                                 height,
1079                                                                                 MM_UTIL_IMG_FMT_RGB888,
1080                                                                                 thumb_info,
1081                                                                                 thumb_width,
1082                                                                                 thumb_height);
1083
1084                         if (err != MS_MEDIA_ERR_NONE) {
1085                                 thumb_err("_media_thumb_resize_data failed - %d", err);
1086                                 SAFE_FREE(thumb_info->data);
1087                                 mm_file_destroy_content_attrs(content);
1088                                 return err;
1089                         }
1090                 } else {
1091                         thumb_info->size = size;
1092                         thumb_info->width = width;
1093                         thumb_info->height = height;
1094                         thumb_info->data = malloc(size);
1095                         memcpy(thumb_info->data, frame, size);
1096                 }
1097
1098                 mm_file_destroy_content_attrs(content);
1099
1100                 /* Get Content Tag attribute for orientatin  */
1101                 MMHandleType tag = (MMHandleType) NULL;
1102                 char *p = NULL;
1103                 int size = -1;
1104                 err = mm_file_create_tag_attrs(&tag, origin_path);
1105                 mm_util_img_rotate_type rot_type = MM_UTIL_ROTATE_0;
1106
1107                 if (err == MM_ERROR_NONE) {
1108                         err = mm_file_get_attrs(tag, &err_msg, MM_FILE_TAG_ROTATE, &p, &size, NULL);
1109                         if (err == MM_ERROR_NONE && size >= 0) {
1110
1111                                 if (p == NULL) {
1112                                         rot_type = MM_UTIL_ROTATE_0;
1113                                 } else {
1114                                         if (strncmp(p, "90", size) == 0) {
1115                                                 rot_type = MM_UTIL_ROTATE_90;
1116                                         } else if(strncmp(p, "180", size) == 0) {
1117                                                 rot_type = MM_UTIL_ROTATE_180;
1118                                         } else if(strncmp(p, "270", size) == 0) {
1119                                                 rot_type = MM_UTIL_ROTATE_270;
1120                                         } else {
1121                                                 rot_type = MM_UTIL_ROTATE_0;
1122                                         }
1123                                 }
1124                         } else {
1125                                 rot_type = MM_UTIL_ROTATE_0;
1126                                 SAFE_FREE(err_msg);
1127                         }
1128                 } else {
1129                         rot_type = MM_UTIL_ROTATE_0;
1130                 }
1131
1132                 err = mm_file_destroy_tag_attrs(tag);
1133                 if (err != MM_ERROR_NONE) {
1134                         thumb_err("fail to free tag attr - err(%x)", err);
1135                 }
1136
1137                 if (rot_type == MM_UTIL_ROTATE_90 || rot_type == MM_UTIL_ROTATE_180 || rot_type == MM_UTIL_ROTATE_270) {
1138                         /* Start to decode to rotate */
1139                         unsigned char *rotated = NULL;
1140                         unsigned int r_w = thumb_info->height;
1141                         unsigned int r_h = thumb_info->width;
1142                         unsigned int r_size = 0;
1143
1144                         if (rot_type == MM_UTIL_ROTATE_180) {
1145                                 r_w = thumb_info->width;
1146                                 r_h = thumb_info->height;
1147                         }
1148
1149                         err = mm_util_get_image_size(MM_UTIL_IMG_FMT_RGB888, r_w, r_h, &r_size);
1150                         if (err != MM_ERROR_NONE) {
1151                                 thumb_err("mm_util_get_image_size failed : %d", err);
1152                                 SAFE_FREE(thumb_info->data);
1153                                 return err;
1154                         }
1155
1156                         //thumb_dbg("Size of Rotated : %d", r_size);
1157                         rotated = (unsigned char *)malloc(r_size);
1158                         err = mm_util_rotate_image(thumb_info->data, thumb_info->width, thumb_info->height,
1159                                                                                 MM_UTIL_IMG_FMT_RGB888,
1160                                                                                 rotated, &r_w, &r_h,
1161                                                                                 rot_type);
1162
1163                         if (err != MM_ERROR_NONE) {
1164                                 thumb_err("mm_util_rotate_image failed : %d", err);
1165                                 SAFE_FREE(thumb_info->data);
1166                                 SAFE_FREE(rotated);
1167                                 return err;
1168                         } else {
1169                                 thumb_dbg("mm_util_rotate_image succeed");
1170                         }
1171
1172                         SAFE_FREE(thumb_info->data);
1173                         thumb_info->data = rotated;
1174                         thumb_info->size = r_size;
1175                         thumb_info->width = r_w;
1176                         thumb_info->height = r_h;
1177                 }
1178
1179                 err = _media_thumb_convert_format(thumb_info, MEDIA_THUMB_RGB888, format);
1180                 if (err != MS_MEDIA_ERR_NONE) {
1181                         thumb_err("_media_thumb_convert_format falied: %d", err);
1182                         SAFE_FREE(thumb_info->data);
1183                         return err;
1184                 }
1185                 pixbuf = gdk_pixbuf_new_from_data (thumb_info->data, GDK_COLORSPACE_RGB, FALSE, 8, thumb_info->width, thumb_info->height, 3*thumb_info->width, NULL, NULL);
1186                 thumb_info->gdkdata = gdk_pixbuf_copy(pixbuf);
1187                 g_object_unref(pixbuf);
1188                 
1189         } else {
1190                 thumb_dbg("no contents information");
1191                 frame = NULL;
1192                 mm_file_destroy_content_attrs(content);
1193
1194                 return MS_MEDIA_ERR_INTERNAL;
1195         }
1196
1197         return err;
1198 }
1199