4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Hyunjun Ko <zzoon.ko@samsung.com>
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
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"
28 #include <sys/types.h>
33 #include <mm_util_magick.h>
35 static void __media_thumb_get_proper_thumb_size(int origin_width, int origin_height, int *thumb_width, int *thumb_height)
37 bool portrait = false;
40 if (origin_width < origin_height)
43 /* Set smaller length to default size */
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;
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;
56 thumb_dbg("proper thumb w: %d h: %d", *thumb_width, *thumb_height);
61 int _media_thumb_general(const char *origin_path, const char *thumb_path, int thumb_width, int thumb_height, media_thumb_info *thumb_info)
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;
69 mm_util_color_format_e format = MM_UTIL_COLOR_NUM;
71 if (thumb_path != NULL) {
72 err = mm_util_resize_P_P(origin_path, thumb_width, thumb_height, thumb_path);
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;
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);
91 int _media_thumb_image(const char *origin_path, char *thumb_path, int thumb_width, int thumb_height, media_thumb_info *thumb_info)
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;
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;
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;
109 __media_thumb_get_proper_thumb_size(origin_w, origin_h, &thumb_width, &thumb_height);
111 if (image_type == IMG_CODEC_PNG) {
112 if (thumb_path != NULL) {
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';
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);
126 thumb_warn("Unsupported image type");
127 return MS_MEDIA_ERR_THUMB_UNSUPPORTED;
133 static void __get_rotation_and_cdis(const char *origin_path, mm_util_magick_rotate_type *rot_type, int *cdis_value)
135 int err = MS_MEDIA_ERR_NONE;
136 MMHandleType tag = (MMHandleType) NULL;
139 char *err_msg = NULL;
141 mm_util_magick_rotate_type _rot_type = MM_UTIL_ROTATE_NUM;
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;
151 err = mm_file_get_attrs(tag, &err_msg, MM_FILE_TAG_ROTATE, &p, &size, NULL);
152 if (err == FILEINFO_ERROR_NONE && size >= 0) {
154 _rot_type = MM_UTIL_ROTATE_0;
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;
163 _rot_type = MM_UTIL_ROTATE_0;
165 thumb_dbg("There is tag rotate : %d", _rot_type);
167 thumb_dbg("There is NOT tag rotate");
168 _rot_type = MM_UTIL_ROTATE_0;
172 err = mm_file_get_attrs(tag, &err_msg, MM_FILE_TAG_CDIS, &_cdis_value, NULL);
173 if (err != FILEINFO_ERROR_NONE) {
178 *rot_type = _rot_type;
179 *cdis_value = _cdis_value;
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);
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)
191 int err = MS_MEDIA_ERR_NONE;
192 MMHandleType content = (MMHandleType) NULL;
193 char *err_msg = NULL;
194 int _video_track_num = 0;
200 if (cdis_value == 1) {
201 thumb_warn("This is CDIS vlaue 1");
202 err = mm_file_create_content_attrs_safe(&content, origin_path);
204 err = mm_file_create_content_attrs(&content, origin_path);
207 if (err != FILEINFO_ERROR_NONE) {
208 thumb_err("mm_file_create_content_attrs fails : %d", err);
209 return MS_MEDIA_ERR_INTERNAL;
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);
216 mm_file_destroy_content_attrs(content);
217 return MS_MEDIA_ERR_INTERNAL;
220 *video_track_num = _video_track_num;
222 if (_video_track_num == 0) {
223 mm_file_destroy_content_attrs(content);
224 return MS_MEDIA_ERR_NONE;
227 err = mm_file_get_attrs(content, &err_msg,
228 MM_FILE_CONTENT_VIDEO_WIDTH,
230 MM_FILE_CONTENT_VIDEO_HEIGHT,
232 MM_FILE_CONTENT_VIDEO_THUMBNAIL, &_frame, /* raw image is RGB888 format */
235 if (err != FILEINFO_ERROR_NONE) {
236 thumb_err("mm_file_get_attrs fails : %s", err_msg);
238 mm_file_destroy_content_attrs(content);
239 return MS_MEDIA_ERR_INTERNAL;
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;
252 *frame = calloc(1, _size);
253 memcpy(*frame, _frame, _size);
255 mm_file_destroy_content_attrs(content);
257 return MS_MEDIA_ERR_NONE;
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)
262 int err = MS_MEDIA_ERR_NONE;
263 mm_util_image_h img = NULL;
264 mm_util_image_h resize_img = NULL;
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;
272 thumb_dbg("Origin:W[%d] H[%d] Proper:W[%d] H[%d]", width, height, thumb_width, thumb_height);
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);
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)
284 err = mm_util_rotate_B_P(resize_img, rot_type, thumb_path);
287 err = mm_util_resize_B_B(img, thumb_width, thumb_height, &resize_img);
288 if (err != MM_UTIL_ERROR_NONE)
291 err = mm_util_rotate_B_B(resize_img, rot_type, dst_img);
294 if (STRING_VALID(thumb_path))
295 err = mm_util_resize_B_P(img, thumb_width, thumb_height, thumb_path);
297 err = mm_util_resize_B_B(img, thumb_width, thumb_height, dst_img);
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);
304 err = mm_util_rotate_B_B(img, rot_type, dst_img);
307 if (STRING_VALID(thumb_path)) {
308 err = mm_util_resize_B_P(img, width, height, thumb_path);
310 err = mm_image_clone_image(img, dst_img);
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;
321 return MS_MEDIA_ERR_NONE;
324 int _media_thumb_video(const char *origin_path, const char *thumb_path, int thumb_width, int thumb_height, media_thumb_info *thumb_info)
326 int err = MS_MEDIA_ERR_NONE;
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;
335 mm_util_color_format_e format = MM_UTIL_COLOR_NUM;
336 mm_util_magick_rotate_type rot_type = MM_UTIL_ROTATE_NUM;
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");
343 if (STRING_VALID(thumb_path)) {
344 err = __get_video_thumb(width, height, frame, size, rot_type, thumb_path, thumb_width, thumb_height, NULL);
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;
356 mm_image_destroy_image(dst_img);
358 thumb_err("Invalid parameter");
359 err = MS_MEDIA_ERR_INVALID_PARAMETER;
367 int _media_thumb_get_hash_name(const char *file_full_path, char *thumb_hash_path, size_t max_thumb_path, uid_t uid)
369 char *hash_name = NULL;
370 char file_ext[255] = { 0 };
371 char *get_path = NULL;
372 char *storage_id = NULL;
374 ms_user_storage_type_e storage_type = -1;
375 int ret = MS_MEDIA_ERR_NONE;
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;
382 _media_thumb_get_file_ext(file_full_path, file_ext, sizeof(file_ext));
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;
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;
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;
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);
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;
413 return MS_MEDIA_ERR_NONE;