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