Remove sync request
[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 "img-codec-parser.h"
28
29 #include <sys/types.h>
30 #include <fcntl.h>
31 #include <unistd.h>
32
33 #include <mm_file.h>
34 #include <mm_util_magick.h>
35
36 int _media_thumb_get_proper_thumb_size(int orig_w, int orig_h, int *thumb_w, int *thumb_h)
37 {
38         bool portrait = false;
39         double ratio;
40
41         if (orig_w < orig_h)
42                 portrait = true;
43
44         /* Set smaller length to default size */
45         if (portrait) {
46                 if (orig_w < *thumb_w)
47                         *thumb_w = orig_w;
48                 ratio = (double)orig_h / (double)orig_w;
49                 *thumb_h = *thumb_w * ratio;
50         } else {
51                 if (orig_h < *thumb_h)
52                         *thumb_h = orig_h;
53                 ratio = (double)orig_w / (double)orig_h;
54                 *thumb_w = *thumb_h * ratio;
55         }
56
57         thumb_dbg("proper thumb w: %d h: %d", *thumb_w, *thumb_h);
58
59         return MS_MEDIA_ERR_NONE;
60 }
61
62 int _media_thumb_general(const char *origin_path, const char *thumb_path, int thumb_width, int thumb_height, media_thumb_info *thumb_info)
63 {
64         int err = MS_MEDIA_ERR_NONE;
65         mm_util_image_h img = NULL;
66         unsigned char *buf = NULL;
67         unsigned int width = 0;
68         unsigned int height = 0;
69         size_t size = 0;
70         mm_util_magick_format format = MM_UTIL_IMG_FMT_NUM;
71
72         if (thumb_path != NULL) {
73                 err = mm_util_resize_P_P(origin_path, thumb_width, thumb_height, thumb_path);
74         } else {
75                 err = mm_util_resize_P_B(origin_path, thumb_width, thumb_height, MM_UTIL_IMG_FMT_BGRA8888, &img);
76                 if (err != MM_UTIL_ERROR_NONE) {
77                         thumb_err("mm_util_resize_P_B failed : %d", err);
78                         return MS_MEDIA_ERR_INTERNAL;
79                 }
80
81                 mm_util_get_image(img, &buf, &width, &height, &size, &format);
82                 thumb_info->data = calloc(1, size);
83                 memcpy(thumb_info->data, buf, size);
84                 thumb_info->size = size;
85                 thumb_info->width = width;
86                 thumb_info->height = height;
87                 SAFE_FREE(buf);
88                 mm_util_destroy_handle(img);
89         }
90
91         return err;
92 }
93
94 int _media_thumb_image(const char *origin_path, char *thumb_path, int thumb_width, int thumb_height, media_thumb_info *thumb_info)
95 {
96         int err = MS_MEDIA_ERR_NONE;
97         ImgCodecType image_type = 0;
98         unsigned int origin_w = 0;
99         unsigned int origin_h = 0;
100
101         err = ImgGetImageInfo(origin_path, &image_type, &origin_w, &origin_h);
102         if (err != MS_MEDIA_ERR_NONE) {
103                 thumb_warn("Getting image info is failed err: %d", err);
104                 return MS_MEDIA_ERR_INTERNAL;
105         }
106
107         if ((image_type != IMG_CODEC_JPEG) && (origin_w * origin_h > THUMB_MAX_ALLOWED_MEM_FOR_THUMB)) {
108                 thumb_warn("This original image is too big");
109                 return MS_MEDIA_ERR_THUMB_TOO_BIG;
110         }
111
112         _media_thumb_get_proper_thumb_size(origin_w, origin_h, &thumb_width, &thumb_height);
113
114         if (image_type == IMG_CODEC_PNG) {
115                 if (thumb_path != NULL) {
116                         char file_ext[10];
117                         err = _media_thumb_get_file_ext(origin_path, file_ext, sizeof(file_ext));
118                         if (strncasecmp(file_ext, "png", 3) == 0) {
119                                 int len = strlen(thumb_path);
120                                 thumb_path[len - 3] = 'p';
121                                 thumb_path[len - 2] = 'n';
122                                 thumb_path[len - 1] = 'g';
123                         }
124                 }
125                 err = _media_thumb_general(origin_path, thumb_path, thumb_width, thumb_height, thumb_info);
126         } else if (image_type == IMG_CODEC_JPEG || image_type == IMG_CODEC_AGIF || image_type == IMG_CODEC_GIF || image_type == IMG_CODEC_BMP || image_type == IMG_CODEC_WBMP) {
127                 err = _media_thumb_general(origin_path, thumb_path, thumb_width, thumb_height, thumb_info);
128         } else {
129                 thumb_warn("Unsupported image type");
130                 return MS_MEDIA_ERR_THUMB_UNSUPPORTED;
131         }
132
133         return err;
134 }
135
136 int _media_thumb_video(const char *origin_path, const char *thumb_path, int thumb_width, int thumb_height, media_thumb_info *thumb_info)
137 {
138         int err = MS_MEDIA_ERR_NONE;
139
140         MMHandleType content = (MMHandleType) NULL;
141         MMHandleType tag = (MMHandleType) NULL;
142
143         char *p = NULL;
144         int cdis_value = 0;
145         void *frame = NULL;
146         int video_track_num = 0;
147         char *err_msg = NULL;
148         int size = 0;
149         int width = 0;
150         int height = 0;
151         mm_util_image_h img = NULL;
152         mm_util_image_h resize_img = NULL;
153         mm_util_image_h dst_img = NULL;
154
155         unsigned char *res_buf = NULL;
156         size_t res_size = 0;
157         unsigned int res_width = 0;
158         unsigned int res_height = 0;
159         mm_util_magick_format res_format;
160
161         /* Get Content Tag attribute for orientation */
162         err = mm_file_create_tag_attrs(&tag, origin_path);
163         mm_util_magick_rotate_type rot_type = MM_UTIL_ROTATE_NUM;
164
165         if (err == FILEINFO_ERROR_NONE) {
166                 err = mm_file_get_attrs(tag, &err_msg, MM_FILE_TAG_ROTATE, &p, &size, NULL);
167                 if (err == FILEINFO_ERROR_NONE && size >= 0) {
168                         if (p == NULL) {
169                                 rot_type = MM_UTIL_ROTATE_0;
170                         } else {
171                                 if (strncmp(p, "90", size) == 0)
172                                         rot_type = MM_UTIL_ROTATE_90;
173                                 else if (strncmp(p, "180", size) == 0)
174                                         rot_type = MM_UTIL_ROTATE_180;
175                                 else if (strncmp(p, "270", size) == 0)
176                                         rot_type = MM_UTIL_ROTATE_270;
177                                 else
178                                         rot_type = MM_UTIL_ROTATE_0;
179                         }
180                         thumb_dbg("There is tag rotate : %d", rot_type);
181                 } else {
182                         thumb_dbg("There is NOT tag rotate");
183                         rot_type = MM_UTIL_ROTATE_0;
184                         SAFE_FREE(err_msg);
185                 }
186
187                 err = mm_file_get_attrs(tag, &err_msg, MM_FILE_TAG_CDIS, &cdis_value, NULL);
188                 if (err != FILEINFO_ERROR_NONE) {
189                         cdis_value = 0;
190                         SAFE_FREE(err_msg);
191                 }
192         } else {
193                 rot_type = MM_UTIL_ROTATE_0;
194                 cdis_value = 0;
195         }
196
197         err = mm_file_destroy_tag_attrs(tag);
198         if (err != FILEINFO_ERROR_NONE) {
199                 thumb_err("fail to free tag attr - err(%x)", err);
200         }
201
202         if (cdis_value == 1) {
203                 thumb_warn("This is CDIS vlaue 1");
204                 err = mm_file_create_content_attrs_safe(&content, origin_path);
205         } else {
206                 err = mm_file_create_content_attrs(&content, origin_path);
207         }
208
209         if (err != FILEINFO_ERROR_NONE) {
210                 thumb_err("mm_file_create_content_attrs fails : %d", err);
211                 return MS_MEDIA_ERR_INTERNAL;
212         }
213
214         err = mm_file_get_attrs(content, &err_msg, MM_FILE_CONTENT_VIDEO_TRACK_COUNT, &video_track_num, NULL);
215         if (err != FILEINFO_ERROR_NONE) {
216                 thumb_err("mm_file_get_attrs fails : %s", err_msg);
217                 SAFE_FREE(err_msg);
218                 goto ERROR;
219         }
220
221         if (video_track_num > 0) {
222                 err = mm_file_get_attrs(content, &err_msg,
223                                         MM_FILE_CONTENT_VIDEO_WIDTH,
224                                         &width,
225                                         MM_FILE_CONTENT_VIDEO_HEIGHT,
226                                         &height,
227                                         MM_FILE_CONTENT_VIDEO_THUMBNAIL, &frame, /* raw image is RGB888 format */
228                                         &size, NULL);
229
230                 if (err != FILEINFO_ERROR_NONE) {
231                         thumb_err("mm_file_get_attrs fails : %s", err_msg);
232                         SAFE_FREE(err_msg);
233                         goto ERROR;
234                 }
235
236                 thumb_dbg("W[%d] H[%d] Size[%d] Frame[%p] Rotate[%d]", width, height, size, frame, rot_type);
237                 if (frame == NULL || width == 0 || height == 0) {
238                         thumb_err("Failed to get frame data");
239                         goto ERROR;
240                 }
241
242                 err = _media_thumb_get_proper_thumb_size(width, height, &thumb_width, &thumb_height);
243                 if (thumb_width <= 0 || thumb_height <= 0) {
244                         thumb_err("Failed to get thumb size");
245                         goto ERROR;
246                 }
247
248                 thumb_dbg("Origin:W[%d] H[%d] Proper:W[%d] H[%d]", width, height, thumb_width, thumb_height);
249
250                 err = mm_util_create_handle(&img, (unsigned char *)frame, width, height, size, MM_UTIL_IMG_FMT_RGB888);
251                 if (width > thumb_width || height > thumb_height) {
252                         if (rot_type != MM_UTIL_ROTATE_0) {
253                                 if (STRING_VALID(thumb_path)) {
254                                         err = mm_util_resize_B_B(img, thumb_width, thumb_height, &resize_img);
255                                         if (err != MM_UTIL_ERROR_NONE)
256                                                 goto ERROR;
257                                         err = mm_util_rotate_B_P(resize_img, rot_type, thumb_path);
258                                 } else {
259                                         err = mm_util_resize_B_B(img, thumb_width, thumb_height, &resize_img);
260                                         if (err != MM_UTIL_ERROR_NONE)
261                                                 goto ERROR;
262                                         err = mm_util_rotate_B_B(resize_img, rot_type, &dst_img);
263                                         if (err != MM_UTIL_ERROR_NONE)
264                                                 goto ERROR;
265                                         mm_util_get_image(dst_img, &res_buf, &res_width, &res_height, &res_size, &res_format);
266                                         thumb_info->data = calloc(1, res_size);
267                                         memcpy(thumb_info->data, res_buf, res_size);
268                                         thumb_info->size = res_size;
269                                         thumb_info->width = res_width;
270                                         thumb_info->height = res_height;
271                                         SAFE_FREE(res_buf);
272                                 }
273                         } else {
274                                 if (STRING_VALID(thumb_path)) {
275                                         err = mm_util_resize_B_P(img, thumb_width, thumb_height, thumb_path);
276                                 } else {
277                                         err = mm_util_resize_B_B(img, thumb_width, thumb_height, &resize_img);
278                                         if (err != MM_UTIL_ERROR_NONE)
279                                                 goto ERROR;
280                                         mm_util_get_image(resize_img, &res_buf, &res_width, &res_height, &res_size, &res_format);
281                                         thumb_info->data = calloc(1, res_size);
282                                         memcpy(thumb_info->data, res_buf, res_size);
283                                         thumb_info->size = res_size;
284                                         thumb_info->width = res_width;
285                                         thumb_info->height = res_height;
286                                         SAFE_FREE(res_buf);
287                                 }
288                         }
289                 } else {
290                         if (rot_type != MM_UTIL_ROTATE_0) {
291                                 if (STRING_VALID(thumb_path)) {
292                                         err = mm_util_rotate_B_P(img, rot_type, thumb_path);
293                                 } else {
294                                         err = mm_util_rotate_B_B(img, rot_type, &dst_img);
295                                         if (err != MM_UTIL_ERROR_NONE)
296                                                 goto ERROR;
297                                         mm_util_get_image(dst_img, &res_buf, &res_width, &res_height, &res_size, &res_format);
298                                         thumb_info->data = calloc(1, res_size);
299                                         memcpy(thumb_info->data, res_buf, res_size);
300                                         thumb_info->size = res_size;
301                                         thumb_info->width = res_width;
302                                         thumb_info->height = res_height;
303                                         SAFE_FREE(res_buf);
304                                 }
305                         } else {
306                                 if (STRING_VALID(thumb_path)) {
307                                         err = mm_util_resize_B_P(img, width, height, thumb_path);
308                                 } else {
309                                         thumb_info->data = calloc(1, size);
310                                         memcpy(thumb_info->data, frame, size);
311                                         thumb_info->size = size;
312                                         thumb_info->width = width;
313                                         thumb_info->height = height;
314                                 }
315                         }
316                 }
317         }
318
319 ERROR:
320         mm_util_destroy_handle(img);
321         mm_util_destroy_handle(resize_img);
322         mm_util_destroy_handle(dst_img);
323         mm_file_destroy_content_attrs(content);
324
325         if (err != MS_MEDIA_ERR_NONE)
326                 return MS_MEDIA_ERR_INTERNAL;
327
328         return MS_MEDIA_ERR_NONE;
329 }
330
331 int _media_thumb_get_hash_name(const char *file_full_path, char *thumb_hash_path, size_t max_thumb_path, uid_t uid)
332 {
333         char *hash_name = NULL;
334         char file_ext[255] = { 0 };
335         char *get_path = NULL;
336         int ret_len = 0;
337         ms_user_storage_type_e storage_type = -1;
338         int ret = MS_MEDIA_ERR_NONE;
339
340         if (file_full_path == NULL || thumb_hash_path == NULL || max_thumb_path <= 0) {
341                 thumb_err("file_full_path==NULL || thumb_hash_path == NULL || max_thumb_path <= 0");
342                 return MS_MEDIA_ERR_INVALID_PARAMETER;
343         }
344
345         _media_thumb_get_file_ext(file_full_path, file_ext, sizeof(file_ext));
346
347         ret = ms_user_get_storage_type(uid, file_full_path, &storage_type);
348         if ((ret != MS_MEDIA_ERR_NONE) || ((storage_type != MS_USER_STORAGE_INTERNAL) && (storage_type != MS_USER_STORAGE_EXTERNAL))) {
349                 thumb_err_slog("origin path(%s) is invalid. err : [%d] storage_type [%d]", file_full_path, ret, storage_type);
350                 return MS_MEDIA_ERR_INVALID_PARAMETER;
351         }
352
353         hash_name = _media_thumb_generate_hash_name(file_full_path);
354         if (hash_name == NULL) {
355                 thumb_err("_media_thumb_generate_hash_name fail");
356                 return MS_MEDIA_ERR_INTERNAL;
357         }
358
359         ret = ms_user_get_thumb_store_path(uid, storage_type, &get_path);
360         if (get_path != NULL)
361                 ret_len = snprintf(thumb_hash_path, max_thumb_path - 1, "%s/.%s-%s.jpg", get_path, file_ext, hash_name);
362
363         SAFE_FREE(get_path);
364
365         if ((ret_len < 0) || (ret_len > (int)max_thumb_path)) {
366                 thumb_err("invalid hash path ret_len[%d]", ret_len);
367                 return MS_MEDIA_ERR_INTERNAL;
368         }
369
370         return MS_MEDIA_ERR_NONE;
371 }