Create New APIs for Creating Video Thumbnail 58/226858/17
authorhj kim <backto.kim@samsung.com>
Fri, 6 Mar 2020 04:21:38 +0000 (13:21 +0900)
committerhj kim <backto.kim@samsung.com>
Fri, 13 Mar 2020 06:52:23 +0000 (15:52 +0900)
To unify duplicated thumbnail extracting codes in libmedia-service, libmedia-thumbnail and thumbnail-util

Change-Id: I1d9fd61349fe02086240db07e3b22a058518c65e

include/media-thumbnail.h
server/thumb-server-internal.c
src/include/media-thumb-internal.h
src/media-thumb-internal.c
src/media-thumbnail.c

index 3e459f8..ec275d5 100755 (executable)
 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
index 33716ca..d65adf7 100755 (executable)
@@ -22,6 +22,7 @@
 #include "thumb-server-internal.h"
 #include "media-thumb-util.h"
 #include "media-thumb-debug.h"
+#include "media-thumbnail.h"
 
 #include <fcntl.h>
 #include <unistd.h>
@@ -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;
index 6876afa..5b82b14 100755 (executable)
@@ -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_*/
index aa7e6aa..bd6ff2d 100755 (executable)
@@ -28,8 +28,6 @@
 #include <sys/types.h>
 #include <fcntl.h>
 #include <unistd.h>
-
-#include <mm_file.h>
 #include <mm_util_magick.h>
 
 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;
index 474325b..dc8a814 100755 (executable)
  *
  */
 
+#include <glib.h>
+#include <mm_file.h>
+#include <mm_util_magick.h>
 #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 <glib.h>
+#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;
+}