From: hj kim Date: Fri, 6 Mar 2020 04:21:38 +0000 (+0900) Subject: Create New APIs for Creating Video Thumbnail X-Git-Tag: accepted/tizen/unified/20200318.130539~2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=7987cc930a4af11c432f21de47b826332590d8ca;p=platform%2Fcore%2Fmultimedia%2Flibmedia-thumbnail.git Create New APIs for Creating Video Thumbnail To unify duplicated thumbnail extracting codes in libmedia-service, libmedia-thumbnail and thumbnail-util Change-Id: I1d9fd61349fe02086240db07e3b22a058518c65e --- diff --git a/include/media-thumbnail.h b/include/media-thumbnail.h index 3e459f8..ec275d5 100755 --- a/include/media-thumbnail.h +++ b/include/media-thumbnail.h @@ -31,9 +31,10 @@ extern "C" { #endif +#define CONTENT_THUMB_DEFAULT_WIDTH 320 +#define CONTENT_THUMB_DEFAULT_HEIGHT 240 typedef int (*ThumbFunc) (int error_code, char* path, void* data); - typedef void (*ThumbRawFunc) (int error_code, int request_id, const char* org_path, int thumb_width, int thumb_height, unsigned char* thumb_data, int thumb_size, void* data); int thumbnail_request_from_db_async(unsigned int request_id, const char *origin_path, ThumbFunc func, void *user_data, uid_t uid); @@ -42,6 +43,12 @@ int thumbnail_request_extract_raw_data_async(int request_id, const char *origin_ int thumbnail_request_cancel_media(unsigned int request_id); int thumbnail_request_cancel_raw_data(int request_id); +int create_video_thumbnail_to_file(const char *path, unsigned int width, unsigned int height, const char *thumb_path, bool auto_rotate); +int create_video_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, bool auto_rotate); + + + + #ifdef __cplusplus } #endif diff --git a/server/thumb-server-internal.c b/server/thumb-server-internal.c index 33716ca..d65adf7 100755 --- a/server/thumb-server-internal.c +++ b/server/thumb-server-internal.c @@ -22,6 +22,7 @@ #include "thumb-server-internal.h" #include "media-thumb-util.h" #include "media-thumb-debug.h" +#include "media-thumbnail.h" #include #include @@ -55,8 +56,8 @@ static int __thumbnail_get_data(const char *origin_path, char *thumb_path) err = _media_thumb_image(origin_path, thumb_path, THUMB_DEFAULT_WIDTH, THUMB_DEFAULT_HEIGHT, NULL); thumb_retvm_if(err != MS_MEDIA_ERR_NONE, err, "_media_thumb_image failed"); } else if (file_type == THUMB_VIDEO_TYPE) { - err = _media_thumb_video(origin_path, thumb_path, THUMB_DEFAULT_WIDTH, THUMB_DEFAULT_HEIGHT, NULL); - thumb_retvm_if(err != MS_MEDIA_ERR_NONE, err, "_media_thumb_video failed"); + err = create_video_thumbnail_to_file(origin_path, CONTENT_THUMB_DEFAULT_WIDTH, CONTENT_THUMB_DEFAULT_HEIGHT, thumb_path, true); + thumb_retvm_if(err != MS_MEDIA_ERR_NONE, err, "create_video_thumbnail_to_file failed"); } else { thumb_err("invalid file type"); return MS_MEDIA_ERR_THUMB_UNSUPPORTED; @@ -93,8 +94,9 @@ static int __thumbnail_get_raw_data(const char *origin_path, unsigned int *width err = _media_thumb_image(origin_path, NULL, thumb_width, thumb_height, &thumb_info); thumb_retvm_if(err != MS_MEDIA_ERR_NONE, err, "_media_thumb_image failed"); } else if (file_type == THUMB_VIDEO_TYPE) { - err = _media_thumb_video(origin_path, NULL, thumb_width, thumb_height, &thumb_info); - thumb_retvm_if(err != MS_MEDIA_ERR_NONE, err, "_media_thumb_video failed"); + err = create_video_thumbnail_to_buffer(origin_path, thumb_width, thumb_height, + &thumb_info.data, &thumb_info.size, &thumb_info.width, &thumb_info.height, true); + thumb_retvm_if(err != MS_MEDIA_ERR_NONE, err, "create_video_thumbnail_to_buffer failed"); } else { thumb_err("invalid file type"); return MS_MEDIA_ERR_THUMB_UNSUPPORTED; diff --git a/src/include/media-thumb-internal.h b/src/include/media-thumb-internal.h index 6876afa..5b82b14 100755 --- a/src/include/media-thumb-internal.h +++ b/src/include/media-thumb-internal.h @@ -48,7 +48,6 @@ typedef struct { } thumbRawUserData; int _media_thumb_image(const char *origin_path, char *thumb_path, unsigned int thumb_width, unsigned int thumb_height, media_thumb_info *thumb_info); -int _media_thumb_video(const char *origin_path, const char *thumb_path, unsigned int thumb_width, unsigned int thumb_height, media_thumb_info *thumb_info); int _media_thumb_get_hash_name(const char *file_full_path, char *thumb_hash_path, size_t max_thumb_path, uid_t uid); #endif /*_MEDIA_THUMB_INTERNAL_H_*/ diff --git a/src/media-thumb-internal.c b/src/media-thumb-internal.c index aa7e6aa..bd6ff2d 100755 --- a/src/media-thumb-internal.c +++ b/src/media-thumb-internal.c @@ -28,8 +28,6 @@ #include #include #include - -#include #include static void __media_thumb_get_proper_thumb_size(unsigned int origin_width, unsigned int origin_height, unsigned int *thumb_width, unsigned int *thumb_height) @@ -123,233 +121,6 @@ int _media_thumb_image(const char *origin_path, char *thumb_path, unsigned int t return err; } -static void __get_rotation_and_cdis(const char *origin_path, mm_util_magick_rotate_type *rot_type, int *cdis_value) -{ - int err = MS_MEDIA_ERR_NONE; - MMHandleType tag = (MMHandleType) NULL; - char *p = NULL; - int size = 0; - int _cdis_value = 0; - mm_util_magick_rotate_type _rot_type = MM_UTIL_ROTATE_NUM; - - /* Get Content Tag attribute for orientation */ - err = mm_file_create_tag_attrs(&tag, origin_path); - if (err != FILEINFO_ERROR_NONE) { - *rot_type = MM_UTIL_ROTATE_0; - *cdis_value = 0; - return; - } - - err = mm_file_get_attrs(tag, MM_FILE_TAG_ROTATE, &p, &size, NULL); - if (err == FILEINFO_ERROR_NONE && size >= 0) { - if (p == NULL) { - _rot_type = MM_UTIL_ROTATE_0; - } else { - if (strncmp(p, "90", size) == 0) - _rot_type = MM_UTIL_ROTATE_90; - else if (strncmp(p, "180", size) == 0) - _rot_type = MM_UTIL_ROTATE_180; - else if (strncmp(p, "270", size) == 0) - _rot_type = MM_UTIL_ROTATE_270; - else - _rot_type = MM_UTIL_ROTATE_0; - } - thumb_dbg("There is tag rotate : %d", _rot_type); - } else { - thumb_dbg("There is NOT tag rotate"); - _rot_type = MM_UTIL_ROTATE_0; - } - - err = mm_file_get_attrs(tag, MM_FILE_TAG_CDIS, &_cdis_value, NULL); - if (err != FILEINFO_ERROR_NONE) - _cdis_value = 0; - - *rot_type = _rot_type; - *cdis_value = _cdis_value; - - err = mm_file_destroy_tag_attrs(tag); - if (err != FILEINFO_ERROR_NONE) { - thumb_err("fail to free tag attr - err(%x)", err); - } - - return; -} - -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) -{ - int err = MS_MEDIA_ERR_NONE; - MMHandleType content = (MMHandleType) NULL; - int _video_track_num = 0; - int _width = 0; - int _height = 0; - size_t _size = 0; - void *_frame = NULL; - - if (cdis_value == 1) { - thumb_warn("This is CDIS vlaue 1"); - err = mm_file_create_content_attrs_safe(&content, origin_path); - } else { - err = mm_file_create_content_attrs(&content, origin_path); - } - - if (err != FILEINFO_ERROR_NONE) { - thumb_err("mm_file_create_content_attrs fails : %d", err); - return MS_MEDIA_ERR_INTERNAL; - } - - err = mm_file_get_attrs(content, MM_FILE_CONTENT_VIDEO_TRACK_COUNT, &_video_track_num, NULL); - if (err != FILEINFO_ERROR_NONE) { - thumb_err("mm_file_get_attrs fails : %d", err); - mm_file_destroy_content_attrs(content); - return MS_MEDIA_ERR_INTERNAL; - } - - *video_track_num = _video_track_num; - - if (_video_track_num == 0) { - mm_file_destroy_content_attrs(content); - return MS_MEDIA_ERR_NONE; - } - - err = mm_file_get_attrs(content, - MM_FILE_CONTENT_VIDEO_WIDTH, - &_width, - MM_FILE_CONTENT_VIDEO_HEIGHT, - &_height, - MM_FILE_CONTENT_VIDEO_THUMBNAIL, &_frame, /* raw image is RGB888 format */ - &_size, NULL); - - if (err != FILEINFO_ERROR_NONE) { - thumb_err("mm_file_get_attrs fails : %d", err); - mm_file_destroy_content_attrs(content); - return MS_MEDIA_ERR_INTERNAL; - } - - thumb_dbg("W[%d] H[%d] Size[%zu] Frame[%p]", _width, _height, _size, _frame); - if (!_frame || !_width || !_height) { - mm_file_destroy_content_attrs(content); - return MS_MEDIA_ERR_INTERNAL; - } - - - *width = _width; - *height = _height; - *size = _size; - *frame = calloc(1, _size); - memcpy(*frame, _frame, _size); - - mm_file_destroy_content_attrs(content); - - return MS_MEDIA_ERR_NONE; -} - -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, unsigned int thumb_width, unsigned int thumb_height, mm_util_image_h *dst_img) -{ - int err = MS_MEDIA_ERR_NONE; - mm_util_image_h img = NULL; - mm_util_image_h resize_img = NULL; - - __media_thumb_get_proper_thumb_size(width, height, &thumb_width, &thumb_height); - if (thumb_width <= 0 || thumb_height <= 0) { - thumb_err("Failed to get thumb size"); - return MS_MEDIA_ERR_INTERNAL; - } - - thumb_dbg("Origin:W[%d] H[%d] Proper:W[%d] H[%d]", width, height, thumb_width, thumb_height); - - err = mm_image_create_image(width, height, MM_UTIL_COLOR_RGB24, (unsigned char *)frame, size, &img); - thumb_retvm_if(err != MM_UTIL_ERROR_NONE, err, "fail to mm_image_create_image [%d]", err); - - if (width > thumb_width || height > thumb_height) { - if (rot_type != MM_UTIL_ROTATE_0) { - if (STRING_VALID(thumb_path)) { - err = mm_util_resize_B_B(img, thumb_width, thumb_height, &resize_img); - if (err != MM_UTIL_ERROR_NONE) - goto ERROR; - - err = mm_util_rotate_B_P(resize_img, rot_type, thumb_path); - - } else { - err = mm_util_resize_B_B(img, thumb_width, thumb_height, &resize_img); - if (err != MM_UTIL_ERROR_NONE) - goto ERROR; - - err = mm_util_rotate_B_B(resize_img, rot_type, dst_img); - } - } else { - if (STRING_VALID(thumb_path)) - err = mm_util_resize_B_P(img, thumb_width, thumb_height, thumb_path); - else - err = mm_util_resize_B_B(img, thumb_width, thumb_height, dst_img); - } - } else { - if (rot_type != MM_UTIL_ROTATE_0) { - if (STRING_VALID(thumb_path)) { - err = mm_util_rotate_B_P(img, rot_type, thumb_path); - } else { - err = mm_util_rotate_B_B(img, rot_type, dst_img); - } - } else { - if (STRING_VALID(thumb_path)) { - err = mm_util_resize_B_P(img, width, height, thumb_path); - } else { - err = mm_image_clone_image(img, dst_img); - } - } - } - -ERROR: - mm_image_destroy_image(img); - mm_image_destroy_image(resize_img); - if (err != MS_MEDIA_ERR_NONE) - return MS_MEDIA_ERR_INTERNAL; - - return MS_MEDIA_ERR_NONE; -} - -int _media_thumb_video(const char *origin_path, const char *thumb_path, unsigned int thumb_width, unsigned int thumb_height, media_thumb_info *thumb_info) -{ - int err = MS_MEDIA_ERR_NONE; - int cdis_value = 0; - void *frame = NULL; - int video_track_num = 0; - unsigned int width = 0; - unsigned int height = 0; - mm_util_image_h dst_img = NULL; - unsigned char *buf = NULL; - size_t size = 0; - mm_util_color_format_e format = MM_UTIL_COLOR_NUM; - mm_util_magick_rotate_type rot_type = MM_UTIL_ROTATE_NUM; - - __get_rotation_and_cdis(origin_path, &rot_type, &cdis_value); - err = __get_video_info(cdis_value, origin_path, &video_track_num, &width, &height, &frame, &size); - thumb_retvm_if(err != MM_UTIL_ERROR_NONE, err, "fail to __get_video_info [%d]", err); - thumb_retvm_if(video_track_num == 0, MM_UTIL_ERROR_NONE, "No video track"); - - if (STRING_VALID(thumb_path)) { - err = __get_video_thumb(width, height, frame, size, rot_type, thumb_path, thumb_width, thumb_height, NULL); - - } else if (thumb_info) { - err = __get_video_thumb(width, height, frame, size, rot_type, NULL, thumb_width, thumb_height, &dst_img); - if (err == MS_MEDIA_ERR_NONE) { - err = mm_image_get_image(dst_img, &width, &height, &format, &buf, &size); - thumb_info->data = buf; - thumb_info->size = size; - thumb_info->width = width; - thumb_info->height = height; - } - - mm_image_destroy_image(dst_img); - } else { - thumb_err("Invalid parameter"); - err = MS_MEDIA_ERR_INVALID_PARAMETER; - } - - SAFE_FREE(frame); - - return err; -} - int _media_thumb_get_hash_name(const char *file_full_path, char *thumb_hash_path, size_t max_thumb_path, uid_t uid) { char *hash_name = NULL; diff --git a/src/media-thumbnail.c b/src/media-thumbnail.c index 474325b..dc8a814 100755 --- a/src/media-thumbnail.c +++ b/src/media-thumbnail.c @@ -19,13 +19,16 @@ * */ +#include +#include +#include #include "media-thumbnail.h" #include "media-thumb-debug.h" #include "media-thumb-util.h" #include "media-thumb-internal.h" #include "media-thumb-ipc.h" -#include +#define THUMB_MAX_ALLOWED_RESOLUTION 2000 int thumbnail_request_from_db_async(unsigned int request_id, const char *origin_path, ThumbFunc func, void *user_data, uid_t uid) { @@ -119,3 +122,349 @@ int thumbnail_request_cancel_raw_data(int request_id) return err; } + +static void __get_rotation_and_cdis(const char *path, mm_util_magick_rotate_type *rot_type, int *cdis_value) +{ + int err = MS_MEDIA_ERR_NONE; + MMHandleType tag = (MMHandleType) NULL; + char *p = NULL; + int size = 0; + int _cdis_value = 0; + mm_util_magick_rotate_type _rot_type = MM_UTIL_ROTATE_0; + + /* Get Content Tag attribute for orientation */ + err = mm_file_create_tag_attrs(&tag, path); + if (err != FILEINFO_ERROR_NONE) + return; + + err = mm_file_get_attrs(tag, MM_FILE_TAG_ROTATE, &p, &size, NULL); + if (err == FILEINFO_ERROR_NONE && size >= 0 && p) { + if (strncmp(p, "90", size) == 0) + _rot_type = MM_UTIL_ROTATE_90; + else if (strncmp(p, "180", size) == 0) + _rot_type = MM_UTIL_ROTATE_180; + else if (strncmp(p, "270", size) == 0) + _rot_type = MM_UTIL_ROTATE_270; + else + _rot_type = MM_UTIL_ROTATE_0; + + thumb_dbg("There is tag rotate : %d", _rot_type); + } + + err = mm_file_get_attrs(tag, MM_FILE_TAG_CDIS, &_cdis_value, NULL); + if (err != FILEINFO_ERROR_NONE) + _cdis_value = 0; + + *rot_type = _rot_type; + *cdis_value = _cdis_value; + + mm_file_destroy_tag_attrs(tag); +} + +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) +{ + int err = MS_MEDIA_ERR_NONE; + MMHandleType content = (MMHandleType) NULL; + int _video_track_num = 0; + unsigned int _width = 0; + unsigned int _height = 0; + size_t _frame_size = 0; + void *_frame = NULL; + + if (cdis_value == 1) { + thumb_warn("This is CDIS vlaue 1"); + err = mm_file_create_content_attrs_safe(&content, path); + } else { + err = mm_file_create_content_attrs(&content, path); + } + thumb_retvm_if(err != FILEINFO_ERROR_NONE, MS_MEDIA_ERR_INTERNAL, "mm_file_create_content_attrs fails : %d", err); + + err = mm_file_get_attrs(content, + MM_FILE_CONTENT_VIDEO_TRACK_COUNT, &_video_track_num, + MM_FILE_CONTENT_VIDEO_WIDTH, &_width, + MM_FILE_CONTENT_VIDEO_HEIGHT, &_height, + MM_FILE_CONTENT_VIDEO_THUMBNAIL, &_frame, &_frame_size, /* raw image is RGB888 format */ + NULL); + + if (err != FILEINFO_ERROR_NONE) { + thumb_err("mm_file_get_attrs fails : %d", err); + mm_file_destroy_content_attrs(content); + return MS_MEDIA_ERR_INTERNAL; + } + + *video_track_num = _video_track_num; + + if (_video_track_num == 0) { + mm_file_destroy_content_attrs(content); + return MS_MEDIA_ERR_NONE; + } + + if (!_frame || !_width || !_height) { + thumb_err("wrong video info W[%d] H[%d] Size[%zu] Frame[%p]", _width, _height, _frame_size, _frame); + mm_file_destroy_content_attrs(content); + return MS_MEDIA_ERR_INTERNAL; + } + + *width = _width; + *height = _height; + *frame_size = _frame_size; + *frame = g_memdup(_frame, _frame_size); + + mm_file_destroy_content_attrs(content); + + return MS_MEDIA_ERR_NONE; +} + + +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_magick_rotate_type *rot_type) +{ + int err = MS_MEDIA_ERR_NONE; + int _cdis_value = 0; + mm_util_magick_rotate_type _rot_type = MM_UTIL_ROTATE_0; + + __get_rotation_and_cdis(path, &_rot_type, &_cdis_value); + err = __get_video_meta(_cdis_value, path, video_track_num, width, height, frame, frame_size); + + *rot_type = _rot_type; + + return err; +} + +static void __media_thumb_get_proper_thumb_size(unsigned int origin_width, unsigned int origin_height, unsigned int *thumb_width, unsigned int *thumb_height) +{ + double ratio = 0.0; + + thumb_retm_if(origin_width == 0, "Invalid origin_width"); + thumb_retm_if(origin_height == 0, "Invalid origin_height"); + thumb_retm_if(!thumb_width, "Invalid thumb_width"); + thumb_retm_if(!thumb_height, "Invalid thumb_height"); + + thumb_dbg("origin thumb w: %d h: %d", *thumb_width, *thumb_height); + + /* Set smaller length to default size */ + if (origin_width < origin_height) { + if (origin_width < *thumb_width) + *thumb_width = origin_width; + ratio = (double)origin_height / (double)origin_width; + *thumb_height = *thumb_width * ratio; + } else { + if (origin_height < *thumb_height) + *thumb_height = origin_height; + ratio = (double)origin_width / (double)origin_height; + *thumb_width = *thumb_height * ratio; + } + + thumb_dbg("proper thumb w: %d h: %d", *thumb_width, *thumb_height); +} + +static int __get_video_thumb_to_file(unsigned int width, unsigned int height, void *frame, size_t frame_size, mm_util_magick_rotate_type rot_type, const char *thumb_path, unsigned int thumb_width, unsigned int thumb_height) +{ + int err = MS_MEDIA_ERR_NONE; + mm_util_image_h img = NULL; + mm_util_image_h resize_img = NULL; + unsigned int thumb_w = thumb_width; + unsigned int thumb_h = thumb_height; + + thumb_retvm_if(!thumb_path, MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid thumb_path"); + + __media_thumb_get_proper_thumb_size(width, height, &thumb_w, &thumb_h); + if (thumb_w == 0 || thumb_h == 0) { + thumb_err("Failed to get thumb size"); + return MS_MEDIA_ERR_INTERNAL; + } + + err = mm_image_create_image(width, height, MM_UTIL_COLOR_RGB24, (unsigned char *)frame, frame_size, &img); + thumb_retvm_if(err != MM_UTIL_ERROR_NONE, err, "fail to mm_image_create_image [%d]", err); + + if (width > thumb_w || height > thumb_h) { + if (rot_type != MM_UTIL_ROTATE_0) { + err = mm_util_resize_B_B(img, thumb_w, thumb_h, &resize_img); + if (err != MM_UTIL_ERROR_NONE) + goto ERROR; + + err = mm_util_rotate_B_P(resize_img, rot_type, thumb_path); + + } else { + err = mm_util_resize_B_P(img, thumb_w, thumb_h, thumb_path); + } + } else { + if (rot_type != MM_UTIL_ROTATE_0) + err = mm_util_rotate_B_P(img, rot_type, thumb_path); + else + err = mm_util_resize_B_P(img, width, height, thumb_path); + } + +ERROR: + mm_image_destroy_image(img); + mm_image_destroy_image(resize_img); + if (err == MS_MEDIA_ERR_NONE) + return err; + + return MS_MEDIA_ERR_INTERNAL; +} + +static int __get_video_thumb_to_buffer(unsigned int width, unsigned int height, void *frame, size_t frame_size, mm_util_magick_rotate_type rot_type, unsigned int thumb_width, unsigned int thumb_height, mm_util_image_h *dst_img) +{ + int err = MS_MEDIA_ERR_NONE; + mm_util_image_h img = NULL; + mm_util_image_h resize_img = NULL; + unsigned int thumb_w = thumb_width; + unsigned int thumb_h = thumb_height; + + __media_thumb_get_proper_thumb_size(width, height, &thumb_w, &thumb_h); + if (thumb_w == 0 || thumb_h == 0) { + thumb_err("Failed to get thumb size"); + return MS_MEDIA_ERR_INTERNAL; + } + + err = mm_image_create_image(width, height, MM_UTIL_COLOR_RGB24, (unsigned char *)frame, frame_size, &img); + thumb_retvm_if(err != MM_UTIL_ERROR_NONE, err, "fail to mm_image_create_image [%d]", err); + + if (width > thumb_w || height > thumb_h) { + if (rot_type != MM_UTIL_ROTATE_0) { + err = mm_util_resize_B_B(img, thumb_w, thumb_h, &resize_img); + if (err != MM_UTIL_ERROR_NONE) + goto ERROR; + + err = mm_util_rotate_B_B(resize_img, rot_type, dst_img); + + } else { + err = mm_util_resize_B_B(img, thumb_w, thumb_h, dst_img); + } + } else { + if (rot_type != MM_UTIL_ROTATE_0) + err = mm_util_rotate_B_B(img, rot_type, dst_img); + else + err = mm_image_clone_image(img, dst_img); + } + +ERROR: + mm_image_destroy_image(img); + mm_image_destroy_image(resize_img); + if (err != MS_MEDIA_ERR_NONE) + return MS_MEDIA_ERR_INTERNAL; + + return MS_MEDIA_ERR_NONE; +} + +static int __check_path_validity(const char *path) +{ + thumb_retvm_if(!path, MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid path"); + + if (access(path, R_OK) < 0) { + if (errno == EACCES || errno == EPERM) { + thumb_err("Fail to open path: Permission Denied [%s]", path); + return MS_MEDIA_ERR_PERMISSION_DENIED; + } else { + thumb_err("Fail to open path: Invalid Path [%s]", path); + return MS_MEDIA_ERR_INVALID_PARAMETER; + } + } + + return MS_MEDIA_ERR_NONE; +} + +static int __check_thumb_path_validity(const char *path) +{ + char *dir_name = NULL; + + thumb_retvm_if(!path, MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid path"); + + dir_name = g_path_get_dirname(path); + if (dir_name) { + if (access(dir_name, W_OK) != 0) { + thumb_err("No permission to write[%s]", dir_name); + SAFE_FREE(dir_name); + return MS_MEDIA_ERR_PERMISSION_DENIED; + } + + SAFE_FREE(dir_name); + } + + return MS_MEDIA_ERR_NONE; +} + +static int __check_parameter_validity_for_file(const char *path, unsigned int width, unsigned int height, const char *thumb_path) +{ + int err = MS_MEDIA_ERR_NONE; + + thumb_retvm_if((width > THUMB_MAX_ALLOWED_RESOLUTION || width == 0), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid width[%d]", width); + thumb_retvm_if((height > THUMB_MAX_ALLOWED_RESOLUTION || height == 0), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid height[%d]", height); + + /* Check path is accessible */ + err = __check_path_validity(path); + thumb_retvm_if(err != MS_MEDIA_ERR_NONE, err, "Invalid path"); + + /* Check thumbnail path is writable */ + err = __check_thumb_path_validity(thumb_path); + thumb_retvm_if(err != MS_MEDIA_ERR_NONE, err, "Invalid thumb_path"); + + return MS_MEDIA_ERR_NONE; +} + +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) +{ + thumb_retvm_if((width > THUMB_MAX_ALLOWED_RESOLUTION || width == 0), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid width[%d]", width); + thumb_retvm_if((height > THUMB_MAX_ALLOWED_RESOLUTION || height == 0), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid height[%d]", height); + thumb_retvm_if(!thumb_buffer || !thumb_size || !thumb_width || !thumb_height, MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid out param"); + + //Check path is accessible + return __check_path_validity(path); +} + +int create_video_thumbnail_to_file(const char *path, unsigned int width, unsigned int height, const char *thumb_path, bool auto_rotate) +{ + int err = MS_MEDIA_ERR_NONE; + int video_track_num = 0; + unsigned int video_width = 0; + unsigned int video_height = 0; + void *frame = NULL; + size_t frame_size = 0; + mm_util_magick_rotate_type rot_type = MM_UTIL_ROTATE_NUM; + + err = __check_parameter_validity_for_file(path, width, height, thumb_path); + thumb_retvm_if(err != MS_MEDIA_ERR_NONE, err, "Invalid parameter"); + + //Get video info + err = __get_video_info(path, &video_track_num, &video_width, &video_height, &frame, &frame_size, &rot_type); + thumb_retvm_if(err != MM_UTIL_ERROR_NONE, err, "fail to __get_video_info [%d]", err); + thumb_retvm_if(video_track_num == 0, MM_UTIL_ERROR_NONE, "No video track"); + + if (!auto_rotate) + rot_type = MM_UTIL_ROTATE_0; + + //Extract thumbnail + return __get_video_thumb_to_file(video_width, video_height, frame, frame_size, rot_type, thumb_path, width, height); +} + +int create_video_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, bool auto_rotate) +{ + int err = MS_MEDIA_ERR_NONE; + int video_track_num = 0; + unsigned int video_w = 0; + unsigned int video_h = 0; + void *frame = NULL; + size_t frame_size = 0; + mm_util_image_h img = NULL; + mm_util_magick_rotate_type rot_type = MM_UTIL_ROTATE_NUM; + + err = __check_parameter_validity_for_buffer(path, width, height, thumb_buffer, thumb_size, thumb_width, thumb_height); + thumb_retvm_if(err != MS_MEDIA_ERR_NONE, err, "Invalid parameter"); + + //Get video info + err = __get_video_info(path, &video_track_num, &video_w, &video_h, &frame, &frame_size, &rot_type); + thumb_retvm_if(err != MM_UTIL_ERROR_NONE, err, "fail to __get_video_info [%d]", err); + thumb_retvm_if(video_track_num == 0, MM_UTIL_ERROR_NONE, "No video track"); + + if (!auto_rotate) + rot_type = MM_UTIL_ROTATE_0; + + //Extract thumbnail + err = __get_video_thumb_to_buffer(video_w, video_h, frame, frame_size, rot_type, width, height, &img); + if (err == MS_MEDIA_ERR_NONE) + err = mm_image_get_image(img, thumb_width, thumb_height, NULL, thumb_buffer, thumb_size); + + mm_image_destroy_image(img); + + return err; +}