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.
23 #include <mm_util_magick.h>
24 #include <media-util.h>
25 #include "media-thumbnail.h"
26 #include "media-thumbnail-debug.h"
28 #define MAX_THUMB_SIZE 2000
30 static void __get_rotation_and_cdis(const char *path, mm_util_rotate_type_e *rot_type, int *cdis_value)
32 int err = MS_MEDIA_ERR_NONE;
33 MMHandleType tag = (MMHandleType) NULL;
37 mm_util_rotate_type_e _rot_type = MM_UTIL_ROTATE_0;
39 /* Get Content Tag attribute for orientation */
40 err = mm_file_create_tag_attrs(&tag, path);
41 if (err != FILEINFO_ERROR_NONE)
44 err = mm_file_get_attrs(tag, MM_FILE_TAG_ROTATE, &p, &size, NULL);
45 if (err == FILEINFO_ERROR_NONE && size >= 0 && p) {
46 if (strncmp(p, "90", size) == 0)
47 _rot_type = MM_UTIL_ROTATE_90;
48 else if (strncmp(p, "180", size) == 0)
49 _rot_type = MM_UTIL_ROTATE_180;
50 else if (strncmp(p, "270", size) == 0)
51 _rot_type = MM_UTIL_ROTATE_270;
53 _rot_type = MM_UTIL_ROTATE_0;
55 thumb_dbg("There is tag rotate : %d", _rot_type);
58 err = mm_file_get_attrs(tag, MM_FILE_TAG_CDIS, &_cdis_value, NULL);
59 if (err != FILEINFO_ERROR_NONE)
62 *rot_type = _rot_type;
63 *cdis_value = _cdis_value;
65 mm_file_destroy_tag_attrs(tag);
68 static int __get_video_meta(int cdis_value, const char *path, int *video_track_num, unsigned int *width, unsigned int *height, void **frame, size_t *frame_size)
70 int err = MS_MEDIA_ERR_NONE;
71 MMHandleType content = (MMHandleType) NULL;
72 int _video_track_num = 0;
73 unsigned int _width = 0;
74 unsigned int _height = 0;
75 size_t _frame_size = 0;
78 if (cdis_value == 1) {
79 thumb_warn("This is CDIS vlaue 1");
80 err = mm_file_create_content_attrs_safe(&content, path);
82 err = mm_file_create_content_attrs(&content, path);
84 thumb_retvm_if(err != FILEINFO_ERROR_NONE, MS_MEDIA_ERR_INTERNAL, "mm_file_create_content_attrs fails : %d", err);
86 err = mm_file_get_attrs(content,
87 MM_FILE_CONTENT_VIDEO_TRACK_COUNT, &_video_track_num,
88 MM_FILE_CONTENT_VIDEO_WIDTH, &_width,
89 MM_FILE_CONTENT_VIDEO_HEIGHT, &_height,
90 MM_FILE_CONTENT_VIDEO_THUMBNAIL, &_frame, &_frame_size, /* raw image is RGB888 format */
93 if (err != FILEINFO_ERROR_NONE) {
94 thumb_err("mm_file_get_attrs fails : %d", err);
95 mm_file_destroy_content_attrs(content);
96 return MS_MEDIA_ERR_INTERNAL;
99 *video_track_num = _video_track_num;
101 if (_video_track_num == 0) {
102 mm_file_destroy_content_attrs(content);
103 return MS_MEDIA_ERR_NONE;
106 if (!_frame || !_width || !_height) {
107 thumb_err("wrong video info W[%d] H[%d] Size[%zu] Frame[%p]", _width, _height, _frame_size, _frame);
108 mm_file_destroy_content_attrs(content);
109 return MS_MEDIA_ERR_INTERNAL;
114 *frame_size = _frame_size;
115 *frame = g_memdup2(_frame, _frame_size);
117 mm_file_destroy_content_attrs(content);
119 return MS_MEDIA_ERR_NONE;
123 static int __get_video_info(const char *path, int *video_track_num, unsigned int *width, unsigned int *height, void **frame, size_t *frame_size, mm_util_rotate_type_e *rot_type)
125 int err = MS_MEDIA_ERR_NONE;
127 mm_util_rotate_type_e _rot_type = MM_UTIL_ROTATE_0;
129 __get_rotation_and_cdis(path, &_rot_type, &_cdis_value);
130 err = __get_video_meta(_cdis_value, path, video_track_num, width, height, frame, frame_size);
133 *rot_type = _rot_type;
138 static void __media_thumb_get_proper_thumb_size(unsigned int origin_width, unsigned int origin_height, unsigned int *thumb_width, unsigned int *thumb_height)
142 thumb_retm_if(origin_width == 0, "Invalid origin_width");
143 thumb_retm_if(origin_height == 0, "Invalid origin_height");
144 thumb_retm_if(!thumb_width, "Invalid thumb_width");
145 thumb_retm_if(!thumb_height, "Invalid thumb_height");
147 thumb_dbg("origin thumb w: %d h: %d", *thumb_width, *thumb_height);
149 /* Set smaller length to default size */
150 if (origin_width < origin_height) {
151 if (origin_width < *thumb_width)
152 *thumb_width = origin_width;
153 ratio = (double)origin_height / (double)origin_width;
154 *thumb_height = *thumb_width * ratio;
156 if (origin_height < *thumb_height)
157 *thumb_height = origin_height;
158 ratio = (double)origin_width / (double)origin_height;
159 *thumb_width = *thumb_height * ratio;
162 thumb_dbg("proper thumb w: %d h: %d", *thumb_width, *thumb_height);
165 static int __get_video_thumb_to_file(unsigned int width, unsigned int height, void *frame, size_t frame_size, mm_util_rotate_type_e rot_type, const char *thumb_path, unsigned int thumb_width, unsigned int thumb_height)
167 int err = MS_MEDIA_ERR_NONE;
168 mm_util_image_h img = NULL;
169 mm_util_image_h resize_img = NULL;
170 unsigned int thumb_w = thumb_width;
171 unsigned int thumb_h = thumb_height;
173 thumb_retvm_if(!thumb_path, MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid thumb_path");
175 __media_thumb_get_proper_thumb_size(width, height, &thumb_w, &thumb_h);
176 thumb_retv_if(thumb_w == 0 || thumb_h == 0, MS_MEDIA_ERR_INTERNAL);
178 err = mm_image_create_image(width, height, MM_UTIL_COLOR_RGB24, (unsigned char *)frame, frame_size, &img);
179 thumb_retvm_if(err != MM_UTIL_ERROR_NONE, err, "fail to mm_image_create_image [%d]", err);
181 if (width > thumb_w || height > thumb_h) {
182 if (rot_type != MM_UTIL_ROTATE_0) {
183 err = mm_util_resize_B_B(img, thumb_w, thumb_h, &resize_img);
184 if (err != MM_UTIL_ERROR_NONE)
187 err = mm_util_rotate_B_P(resize_img, rot_type, thumb_path);
190 err = mm_util_resize_B_P(img, thumb_w, thumb_h, thumb_path);
193 if (rot_type != MM_UTIL_ROTATE_0)
194 err = mm_util_rotate_B_P(img, rot_type, thumb_path);
196 err = mm_util_resize_B_P(img, width, height, thumb_path);
200 mm_image_destroy_image(img);
201 mm_image_destroy_image(resize_img);
203 return (err == MM_UTIL_ERROR_NONE) ? MS_MEDIA_ERR_NONE : MS_MEDIA_ERR_INTERNAL;
206 static int __get_video_thumb_to_buffer(unsigned int width, unsigned int height, void *frame, size_t frame_size, unsigned int thumb_width, unsigned int thumb_height, mm_util_image_h *dst_img)
208 int err = MS_MEDIA_ERR_NONE;
209 mm_util_image_h img = NULL;
210 unsigned int thumb_w = thumb_width;
211 unsigned int thumb_h = thumb_height;
213 __media_thumb_get_proper_thumb_size(width, height, &thumb_w, &thumb_h);
214 thumb_retv_if(thumb_w == 0 || thumb_h == 0, MS_MEDIA_ERR_INTERNAL);
216 err = mm_image_create_image(width, height, MM_UTIL_COLOR_RGB24, (unsigned char *)frame, frame_size, &img);
217 thumb_retvm_if(err != MM_UTIL_ERROR_NONE, err, "fail to mm_image_create_image [%d]", err);
219 if (width > thumb_w || height > thumb_h)
220 err = mm_util_resize_B_B(img, thumb_w, thumb_h, dst_img);
222 err = mm_image_clone_image(img, dst_img);
223 mm_image_destroy_image(img);
225 return (err == MM_UTIL_ERROR_NONE) ? MS_MEDIA_ERR_NONE : MS_MEDIA_ERR_INTERNAL;
228 static int __check_path_validity(const char *path)
230 thumb_retvm_if(!path, MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid path");
232 if (access(path, R_OK) < 0) {
233 if (errno == EACCES || errno == EPERM) {
234 thumb_err("Fail to open path: Permission Denied [%s]", path);
235 return MS_MEDIA_ERR_PERMISSION_DENIED;
237 thumb_err("Fail to open path: Invalid Path [%s]", path);
238 return MS_MEDIA_ERR_INVALID_PARAMETER;
242 return MS_MEDIA_ERR_NONE;
245 static int __check_thumb_path_validity(const char *path)
247 char *dir_name = NULL;
248 int ret = MS_MEDIA_ERR_NONE;
250 thumb_retvm_if(!THUMB_STRING_VALID(path), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid path");
252 dir_name = g_path_get_dirname(path);
254 if (access(dir_name, W_OK) != 0) {
255 if (errno == EACCES || errno == EPERM) {
256 thumb_err("No permission to write[%s]", dir_name);
257 ret = MS_MEDIA_ERR_PERMISSION_DENIED;
259 thumb_err("Does not exists[%s]", dir_name);
260 ret = MS_MEDIA_ERR_INVALID_PARAMETER;
269 static int __check_parameter_validity_for_file(const char *path, unsigned int width, unsigned int height, const char *thumb_path)
271 int err = MS_MEDIA_ERR_NONE;
273 thumb_retvm_if((width > MAX_THUMB_SIZE || width == 0), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid width[%d]", width);
274 thumb_retvm_if((height > MAX_THUMB_SIZE || height == 0), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid height[%d]", height);
276 /* Check path is accessible */
277 err = __check_path_validity(path);
278 thumb_retvm_if(err != MS_MEDIA_ERR_NONE, err, "Invalid path");
280 /* Check thumbnail path is writable */
281 err = __check_thumb_path_validity(thumb_path);
282 thumb_retvm_if(err != MS_MEDIA_ERR_NONE, err, "Invalid thumb_path");
284 return MS_MEDIA_ERR_NONE;
287 static int __check_parameter_validity_for_buffer(const char *path, unsigned int width, unsigned int height, unsigned char **thumb_buffer, size_t *thumb_size, unsigned int *thumb_width, unsigned int *thumb_height)
289 thumb_retvm_if((width > MAX_THUMB_SIZE || width == 0), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid width[%d]", width);
290 thumb_retvm_if((height > MAX_THUMB_SIZE || height == 0), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid height[%d]", height);
291 thumb_retvm_if(!thumb_buffer || !thumb_size || !thumb_width || !thumb_height, MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid out param");
293 //Check path is accessible
294 return __check_path_validity(path);
297 int create_video_thumbnail_to_file(const char *path, unsigned int width, unsigned int height, const char *thumb_path, bool auto_rotate)
299 int err = MS_MEDIA_ERR_NONE;
300 int video_track_num = 0;
301 unsigned int video_width = 0;
302 unsigned int video_height = 0;
304 size_t frame_size = 0;
305 mm_util_rotate_type_e rot_type = MM_UTIL_ROTATE_NUM;
307 err = __check_parameter_validity_for_file(path, width, height, thumb_path);
308 thumb_retvm_if(err != MS_MEDIA_ERR_NONE, err, "Invalid parameter");
311 err = __get_video_info(path, &video_track_num, &video_width, &video_height, &frame, &frame_size, &rot_type);
312 thumb_retvm_if(err != MM_UTIL_ERROR_NONE, err, "fail to __get_video_info [%d]", err);
313 thumb_retvm_if(video_track_num == 0, MM_UTIL_ERROR_NONE, "No video track");
316 rot_type = MM_UTIL_ROTATE_0;
319 err = __get_video_thumb_to_file(video_width, video_height, frame, frame_size, rot_type, thumb_path, width, height);
325 int create_video_thumbnail_to_buffer(const char *path,
328 unsigned char **thumb_buffer,
330 unsigned int *thumb_width,
331 unsigned int *thumb_height)
333 int err = MS_MEDIA_ERR_NONE;
334 int video_track_num = 0;
335 unsigned int video_w = 0;
336 unsigned int video_h = 0;
338 size_t frame_size = 0;
339 mm_util_image_h img = NULL;
341 err = __check_parameter_validity_for_buffer(path, width, height, thumb_buffer, thumb_size, thumb_width, thumb_height);
342 thumb_retvm_if(err != MS_MEDIA_ERR_NONE, err, "Invalid parameter");
345 err = __get_video_info(path, &video_track_num, &video_w, &video_h, &frame, &frame_size, NULL);
346 thumb_retvm_if(err != MM_UTIL_ERROR_NONE, err, "fail to __get_video_info [%d]", err);
347 thumb_retvm_if(video_track_num == 0, MM_UTIL_ERROR_NONE, "No video track");
350 err = __get_video_thumb_to_buffer(video_w, video_h, frame, frame_size, width, height, &img);
352 if (err != MS_MEDIA_ERR_NONE)
355 err = mm_image_get_image(img, thumb_width, thumb_height, NULL, thumb_buffer, thumb_size);
356 mm_image_destroy_image(img);
361 static int __adjust_thumb_ratio(const char *path, unsigned int *width, unsigned int *height)
363 int err = MS_MEDIA_ERR_NONE;
364 unsigned int image_w = 0;
365 unsigned int image_h = 0;
366 mm_util_img_codec_type image_type = 0;
368 err = mm_util_extract_image_info(path, &image_type, &image_w, &image_h);
369 thumb_retvm_if(err != MM_UTIL_ERROR_NONE, MS_MEDIA_ERR_INTERNAL, "mm_util_extract_image_info: %d", err);
370 thumb_retvm_if(image_type == IMG_CODEC_UNKNOWN_TYPE, MS_MEDIA_ERR_THUMB_UNSUPPORTED, "Unsupported image codec");
372 __media_thumb_get_proper_thumb_size(image_w, image_h, width, height);
374 return MS_MEDIA_ERR_NONE;
377 int create_image_thumbnail_to_file(const char *path, unsigned int width, unsigned int height, const char *thumb_path, bool auto_rotate)
379 int err = MS_MEDIA_ERR_NONE;
380 unsigned int thumb_w = width;
381 unsigned int thumb_h = height;
383 err = __check_parameter_validity_for_file(path, width, height, thumb_path);
384 thumb_retvm_if(err != MS_MEDIA_ERR_NONE, err, "Invalid parameter");
386 err = __adjust_thumb_ratio(path, &thumb_w, &thumb_h);
387 thumb_retvm_if(err != MS_MEDIA_ERR_NONE, err, "__adjust_thumb_ratio failed");
390 err = mm_util_resize_and_rotate_P_P(path, thumb_w, thumb_h, thumb_path);
392 err = mm_util_resize_P_P(path, thumb_w, thumb_h, thumb_path);
393 thumb_retvm_if(err != MM_UTIL_ERROR_NONE, MS_MEDIA_ERR_INTERNAL, "mm_util_resize_P_P failed : %d", err);
395 return MS_MEDIA_ERR_NONE;
398 int create_image_thumbnail_to_buffer(const char *path, unsigned int width, unsigned int height, unsigned char **thumb_buffer, size_t *thumb_size, unsigned int *thumb_width, unsigned int *thumb_height)
400 int err = MS_MEDIA_ERR_NONE;
401 unsigned int thumb_w = width;
402 unsigned int thumb_h = height;
403 mm_util_image_h img = NULL;
405 err = __check_parameter_validity_for_buffer(path, width, height, thumb_buffer, thumb_size, thumb_width, thumb_height);
406 thumb_retvm_if(err != MS_MEDIA_ERR_NONE, err, "Invalid parameter");
408 err = __adjust_thumb_ratio(path, &thumb_w, &thumb_h);
409 thumb_retvm_if(err != MS_MEDIA_ERR_NONE, err, "__adjust_thumb_ratio failed");
411 err = mm_util_resize_P_B(path, thumb_w, thumb_h, MM_UTIL_COLOR_BGRA, &img);
412 thumb_retvm_if(err != MM_UTIL_ERROR_NONE, MS_MEDIA_ERR_INTERNAL, "mm_util_resize_P_B failed : %d", err);
414 err = mm_image_get_image(img, thumb_width, thumb_height, NULL, thumb_buffer, thumb_size);
416 mm_image_destroy_image(img);