Remove parameter with fixed value
[platform/core/multimedia/libmedia-thumbnail.git] / src / media-thumbnail.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 <mm_file.h>
23 #include <mm_util_magick.h>
24 #include <media-util.h>
25 #include "media-thumbnail.h"
26 #include "media-thumbnail-debug.h"
27
28 #define MAX_THUMB_SIZE 2000
29
30 static void __get_rotation_and_cdis(const char *path, mm_util_rotate_type_e *rot_type, int *cdis_value)
31 {
32         int err = MS_MEDIA_ERR_NONE;
33         MMHandleType tag = (MMHandleType) NULL;
34         char *p = NULL;
35         int size = 0;
36         int _cdis_value = 0;
37         mm_util_rotate_type_e _rot_type = MM_UTIL_ROTATE_0;
38
39         /* Get Content Tag attribute for orientation */
40         err = mm_file_create_tag_attrs(&tag, path);
41         if (err != FILEINFO_ERROR_NONE)
42                 return;
43
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;
52                 else
53                         _rot_type = MM_UTIL_ROTATE_0;
54
55                 thumb_dbg("There is tag rotate : %d", _rot_type);
56         }
57
58         err = mm_file_get_attrs(tag, MM_FILE_TAG_CDIS, &_cdis_value, NULL);
59         if (err != FILEINFO_ERROR_NONE)
60                 _cdis_value = 0;
61
62         *rot_type = _rot_type;
63         *cdis_value = _cdis_value;
64
65         mm_file_destroy_tag_attrs(tag);
66 }
67
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)
69 {
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;
76         void *_frame = NULL;
77
78         if (cdis_value == 1) {
79                 thumb_warn("This is CDIS vlaue 1");
80                 err = mm_file_create_content_attrs_safe(&content, path);
81         } else {
82                 err = mm_file_create_content_attrs(&content, path);
83         }
84         thumb_retvm_if(err != FILEINFO_ERROR_NONE, MS_MEDIA_ERR_INTERNAL, "mm_file_create_content_attrs fails : %d", err);
85
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 */
91                                 NULL);
92
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;
97         }
98
99         *video_track_num = _video_track_num;
100
101         if (_video_track_num == 0) {
102                 mm_file_destroy_content_attrs(content);
103                 return MS_MEDIA_ERR_NONE;
104         }
105
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;
110         }
111
112         *width = _width;
113         *height = _height;
114         *frame_size = _frame_size;
115         *frame = g_memdup2(_frame, _frame_size);
116
117         mm_file_destroy_content_attrs(content);
118
119         return MS_MEDIA_ERR_NONE;
120 }
121
122
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)
124 {
125         int err = MS_MEDIA_ERR_NONE;
126         int _cdis_value = 0;
127         mm_util_rotate_type_e _rot_type = MM_UTIL_ROTATE_0;
128
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);
131
132         if (rot_type)
133                 *rot_type = _rot_type;
134
135         return err;
136 }
137
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)
139 {
140         double ratio = 0.0;
141
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");
146
147         thumb_dbg("origin thumb w: %d h: %d", *thumb_width, *thumb_height);
148
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;
155         } else {
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;
160         }
161
162         thumb_dbg("proper thumb w: %d h: %d", *thumb_width, *thumb_height);
163 }
164
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)
166 {
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;
172
173         thumb_retvm_if(!thumb_path, MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid thumb_path");
174
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);
177
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);
180
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)
185                                 goto ERROR;
186
187                         err = mm_util_rotate_B_P(resize_img, rot_type, thumb_path);
188
189                 } else {
190                         err = mm_util_resize_B_P(img, thumb_w, thumb_h, thumb_path);
191                 }
192         } else {
193                 if (rot_type != MM_UTIL_ROTATE_0)
194                         err = mm_util_rotate_B_P(img, rot_type, thumb_path);
195                 else
196                         err = mm_util_resize_B_P(img, width, height, thumb_path);
197         }
198
199 ERROR:
200         mm_image_destroy_image(img);
201         mm_image_destroy_image(resize_img);
202
203         return (err == MM_UTIL_ERROR_NONE) ? MS_MEDIA_ERR_NONE : MS_MEDIA_ERR_INTERNAL;
204 }
205
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)
207 {
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;
212
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);
215
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);
218
219         if (width > thumb_w || height > thumb_h)
220                 err = mm_util_resize_B_B(img, thumb_w, thumb_h, dst_img);
221         else
222                 err = mm_image_clone_image(img, dst_img);
223         mm_image_destroy_image(img);
224
225         return (err == MM_UTIL_ERROR_NONE) ? MS_MEDIA_ERR_NONE : MS_MEDIA_ERR_INTERNAL;
226 }
227
228 static int __check_path_validity(const char *path)
229 {
230         thumb_retvm_if(!path, MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid path");
231
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;
236                 } else {
237                         thumb_err("Fail to open path: Invalid Path [%s]", path);
238                         return MS_MEDIA_ERR_INVALID_PARAMETER;
239                 }
240         }
241
242         return MS_MEDIA_ERR_NONE;
243 }
244
245 static int __check_thumb_path_validity(const char *path)
246 {
247         char *dir_name = NULL;
248         int ret = MS_MEDIA_ERR_NONE;
249
250         thumb_retvm_if(!THUMB_STRING_VALID(path), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid path");
251
252         dir_name = g_path_get_dirname(path);
253
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;
258                 } else {
259                         thumb_err("Does not exists[%s]", dir_name);
260                         ret = MS_MEDIA_ERR_INVALID_PARAMETER;
261                 }
262         }
263
264         g_free(dir_name);
265
266         return ret;
267 }
268
269 static int __check_parameter_validity_for_file(const char *path, unsigned int width, unsigned int height, const char *thumb_path)
270 {
271         int err = MS_MEDIA_ERR_NONE;
272
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);
275
276         /* Check path is accessible */
277         err = __check_path_validity(path);
278         thumb_retvm_if(err != MS_MEDIA_ERR_NONE, err, "Invalid path");
279
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");
283
284         return MS_MEDIA_ERR_NONE;
285 }
286
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)
288 {
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");
292
293         //Check path is accessible
294         return __check_path_validity(path);
295 }
296
297 int create_video_thumbnail_to_file(const char *path, unsigned int width, unsigned int height, const char *thumb_path, bool auto_rotate)
298 {
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;
303         void *frame = NULL;
304         size_t frame_size = 0;
305         mm_util_rotate_type_e rot_type = MM_UTIL_ROTATE_NUM;
306
307         err = __check_parameter_validity_for_file(path, width, height, thumb_path);
308         thumb_retvm_if(err != MS_MEDIA_ERR_NONE, err, "Invalid parameter");
309
310         //Get video info
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");
314
315         if (!auto_rotate)
316                 rot_type = MM_UTIL_ROTATE_0;
317
318         //Extract thumbnail
319         err = __get_video_thumb_to_file(video_width, video_height, frame, frame_size, rot_type, thumb_path, width, height);
320         g_free(frame);
321
322         return err;
323 }
324
325 int create_video_thumbnail_to_buffer(const char *path,
326                                                                 unsigned int width,
327                                                                 unsigned int height,
328                                                                 unsigned char **thumb_buffer,
329                                                                 size_t *thumb_size,
330                                                                 unsigned int *thumb_width,
331                                                                 unsigned int *thumb_height)
332 {
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;
337         void *frame = NULL;
338         size_t frame_size = 0;
339         mm_util_image_h img = NULL;
340
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");
343
344         //Get video info
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");
348
349         //Extract thumbnail
350         err = __get_video_thumb_to_buffer(video_w, video_h, frame, frame_size, width, height, &img);
351         g_free(frame);
352         if (err != MS_MEDIA_ERR_NONE)
353                 return err;
354
355         err = mm_image_get_image(img, thumb_width, thumb_height, NULL, thumb_buffer, thumb_size);
356         mm_image_destroy_image(img);
357
358         return err;
359 }
360
361 static int __adjust_thumb_ratio(const char *path, unsigned int *width, unsigned int *height)
362 {
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;
367
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");
371
372         __media_thumb_get_proper_thumb_size(image_w, image_h, width, height);
373
374         return MS_MEDIA_ERR_NONE;
375 }
376
377 int create_image_thumbnail_to_file(const char *path, unsigned int width, unsigned int height, const char *thumb_path, bool auto_rotate)
378 {
379         int err = MS_MEDIA_ERR_NONE;
380         unsigned int thumb_w = width;
381         unsigned int thumb_h = height;
382
383         err = __check_parameter_validity_for_file(path, width, height, thumb_path);
384         thumb_retvm_if(err != MS_MEDIA_ERR_NONE, err, "Invalid parameter");
385
386         err = __adjust_thumb_ratio(path, &thumb_w, &thumb_h);
387         thumb_retvm_if(err != MS_MEDIA_ERR_NONE, err, "__adjust_thumb_ratio failed");
388
389         if (auto_rotate)
390                 err = mm_util_resize_and_rotate_P_P(path, thumb_w, thumb_h, thumb_path);
391         else
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);
394
395         return MS_MEDIA_ERR_NONE;
396 }
397
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)
399 {
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;
404
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");
407
408         err = __adjust_thumb_ratio(path, &thumb_w, &thumb_h);
409         thumb_retvm_if(err != MS_MEDIA_ERR_NONE, err, "__adjust_thumb_ratio failed");
410
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);
413
414         err = mm_image_get_image(img, thumb_width, thumb_height, NULL, thumb_buffer, thumb_size);
415
416         mm_image_destroy_image(img);
417
418         return err;
419 }