Use macro instead
[platform/core/multimedia/libmm-fileinfo.git] / mm_file.c
1 /*
2  * libmm-fileinfo
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Haejeong Kim <backto.kim@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 <stdio.h>
23 #include <stdlib.h>
24 #include <unistd.h>     /*for access*/
25 #include <string.h>     /*for strXXX*/
26 #include <dlfcn.h>
27
28 /* exported MM header files */
29 #include <mm_file.h>
30 #include <mm_attrs.h>
31
32 /* internal MM File headers */
33 #include "mm_file_debug.h"
34 #include "mm_file_formats.h"
35 #include "mm_file_format_frame.h"
36 #include "mm_file_codecs.h"
37 #include "mm_file_utils.h"
38
39
40 #include <sys/time.h>
41
42 /*#define CHECK_TIME */
43
44 #ifdef CHECK_TIME
45 int64_t gettime(void)
46 {
47         struct timeval tv;
48         gettimeofday(&tv, NULL);
49         return (int64_t)tv.tv_sec * 1000000 + tv.tv_usec;
50 }
51 #endif
52
53
54 /**
55  * Defines.
56  */
57
58 #ifndef ARRAY_SIZE
59 #define ARRAY_SIZE(arr)         (sizeof(arr) / sizeof((arr)[0]))
60 #endif
61
62 #define _SEEK_POINT_    3000            /*1000 = 1 seconds*/
63
64 #define MM_FILE_TAG_SYNCLYRICS  "tag-synclyrics"        /**< Synchronized Lyrics Information*/
65
66
67 enum {
68         MM_FILE_TAG,
69         MM_FILE_CONTENTS,
70         MM_FILE_INVALID,
71 };
72
73 typedef enum {
74         MM_FILE_PARSE_TYPE_SIMPLE,              /*parse audio/video track num only*/
75         MM_FILE_PARSE_TYPE_NORMAL,              /*parse infomation without thumbnail*/
76         MM_FILE_PARSE_TYPE_ALL,                 /*parse all infomation*/
77         MM_FILE_PARSE_TYPE_SAFE,                /*parse infomation without both thumbnail and stream full-searching*/
78 } MMFILE_PARSE_TYPE;
79
80 typedef struct {
81         int     type;
82         int     audio_track_num;
83         int     video_track_num;
84         bool is_uhqa;
85 } MMFILE_PARSE_INFO;
86
87 typedef struct {
88         void *formatFuncHandle;
89         void *codecFuncHandle;
90 } MMFILE_FUNC_HANDLE;
91
92
93
94 /**
95  * global values.
96  */
97 static MMAttrsConstructInfo g_tag_attrs[] = {
98         {(char *)"tag-artist",                  MM_ATTRS_TYPE_STRING,   MM_ATTRS_FLAG_RW, (void *)NULL},
99         {(char *)"tag-title",                   MM_ATTRS_TYPE_STRING,   MM_ATTRS_FLAG_RW, (void *)NULL},
100         {(char *)"tag-album",                   MM_ATTRS_TYPE_STRING,   MM_ATTRS_FLAG_RW, (void *)NULL},
101         {(char *)"tag-album-artist",    MM_ATTRS_TYPE_STRING,   MM_ATTRS_FLAG_RW, (void *)NULL},
102         {(char *)"tag-genre",                   MM_ATTRS_TYPE_STRING,   MM_ATTRS_FLAG_RW, (void *)NULL},
103         {(char *)"tag-author",                  MM_ATTRS_TYPE_STRING,   MM_ATTRS_FLAG_RW, (void *)NULL},
104         {(char *)"tag-copyright",               MM_ATTRS_TYPE_STRING,   MM_ATTRS_FLAG_RW, (void *)NULL},
105         {(char *)"tag-date",                    MM_ATTRS_TYPE_STRING,   MM_ATTRS_FLAG_RW, (void *)NULL},
106         {(char *)"tag-description",             MM_ATTRS_TYPE_STRING,   MM_ATTRS_FLAG_RW, (void *)NULL},
107         {(char *)"tag-comment",         MM_ATTRS_TYPE_STRING,   MM_ATTRS_FLAG_RW, (void *)NULL},
108         {(char *)"tag-artwork",         MM_ATTRS_TYPE_DATA,     MM_ATTRS_FLAG_RW, (void *)NULL},
109         {(char *)"tag-artwork-size",    MM_ATTRS_TYPE_INT,              MM_ATTRS_FLAG_RW, (void *)0},
110         {(char *)"tag-artwork-mime",    MM_ATTRS_TYPE_STRING,   MM_ATTRS_FLAG_RW, (void *)NULL},
111         {(char *)"tag-track-num",               MM_ATTRS_TYPE_STRING,   MM_ATTRS_FLAG_RW, (void *)NULL},
112         {(char *)"tag-classification",  MM_ATTRS_TYPE_STRING,   MM_ATTRS_FLAG_RW, (void *)NULL},
113         {(char *)"tag-rating",                  MM_ATTRS_TYPE_STRING,   MM_ATTRS_FLAG_RW, (void *)NULL},
114         {(char *)"tag-longitude",               MM_ATTRS_TYPE_DOUBLE,   MM_ATTRS_FLAG_RW, (void *)0},
115         {(char *)"tag-latitude",                MM_ATTRS_TYPE_DOUBLE,   MM_ATTRS_FLAG_RW, (void *)0},
116         {(char *)"tag-altitude",                MM_ATTRS_TYPE_DOUBLE,   MM_ATTRS_FLAG_RW, (void *)0},
117         {(char *)"tag-conductor",               MM_ATTRS_TYPE_STRING,   MM_ATTRS_FLAG_RW, (void *)NULL},
118         {(char *)"tag-unsynclyrics",    MM_ATTRS_TYPE_STRING,   MM_ATTRS_FLAG_RW, (void *)NULL},
119         {(char *)"tag-synclyrics-num",  MM_ATTRS_TYPE_INT,              MM_ATTRS_FLAG_RW, (void *)0},
120         {(char *)"tag-synclyrics",              MM_ATTRS_TYPE_DATA,     MM_ATTRS_FLAG_RW, (void *)NULL},
121         {(char *)"tag-recdate",         MM_ATTRS_TYPE_STRING,   MM_ATTRS_FLAG_RW, (void *)NULL},
122         {(char *)"tag-part-of-set",             MM_ATTRS_TYPE_STRING,   MM_ATTRS_FLAG_RW, (void *)NULL},
123         {(char *)"tag-rotate",                  MM_ATTRS_TYPE_STRING,   MM_ATTRS_FLAG_RW, (void *)NULL},
124         {(char *)"tag-cdis",                    MM_ATTRS_TYPE_INT,              MM_ATTRS_FLAG_RW, (void *)0},
125         {(char *)"tag-smta",                    MM_ATTRS_TYPE_INT,              MM_ATTRS_FLAG_RW, (void *)0},
126         {(char *)"tag-spherical",                                       MM_ATTRS_TYPE_INT,              MM_ATTRS_FLAG_RW, (void *)0},
127         {(char *)"tag-stitched",                                        MM_ATTRS_TYPE_INT,              MM_ATTRS_FLAG_RW, (void *)0},
128         {(char *)"tag-stitching-software",                      MM_ATTRS_TYPE_STRING,   MM_ATTRS_FLAG_RW, (void *)NULL},
129         {(char *)"tag-projection-type",                         MM_ATTRS_TYPE_STRING,   MM_ATTRS_FLAG_RW, (void *)NULL},
130         {(char *)"tag-stereo-mode",                                     MM_ATTRS_TYPE_STRING,   MM_ATTRS_FLAG_RW, (void *)NULL},
131         {(char *)"tag-source-count",                            MM_ATTRS_TYPE_INT,              MM_ATTRS_FLAG_RW, (void *)0},
132         {(char *)"tag-init-view-heading",                       MM_ATTRS_TYPE_INT,              MM_ATTRS_FLAG_RW, (void *)0},
133         {(char *)"tag-init-view-pitch",                         MM_ATTRS_TYPE_INT,              MM_ATTRS_FLAG_RW, (void *)0},
134         {(char *)"tag-init-view-roll",                          MM_ATTRS_TYPE_INT,              MM_ATTRS_FLAG_RW, (void *)0},
135         {(char *)"tag-timestamp",                                       MM_ATTRS_TYPE_INT,              MM_ATTRS_FLAG_RW, (void *)0},
136         {(char *)"tag-full-pano-width",                         MM_ATTRS_TYPE_INT,              MM_ATTRS_FLAG_RW, (void *)0},
137         {(char *)"tag-full-pano-height",                        MM_ATTRS_TYPE_INT,              MM_ATTRS_FLAG_RW, (void *)0},
138         {(char *)"tag-cropped-area-image-width",        MM_ATTRS_TYPE_INT,              MM_ATTRS_FLAG_RW, (void *)0},
139         {(char *)"tag-cropped-area-image-height",       MM_ATTRS_TYPE_INT,              MM_ATTRS_FLAG_RW, (void *)0},
140         {(char *)"tag-cropped-area-left",                       MM_ATTRS_TYPE_INT,              MM_ATTRS_FLAG_RW, (void *)0},
141         {(char *)"tag-cropped-area-top",                        MM_ATTRS_TYPE_INT,              MM_ATTRS_FLAG_RW, (void *)0},
142         {(char *)"tag-ambisonic-type",                          MM_ATTRS_TYPE_INT,              MM_ATTRS_FLAG_RW, (void *)0},
143         {(char *)"tag-ambisonic-format",                        MM_ATTRS_TYPE_INT,              MM_ATTRS_FLAG_RW, (void *)0},
144         {(char *)"tag-ambisonic-order",                         MM_ATTRS_TYPE_INT,              MM_ATTRS_FLAG_RW, (void *)0},
145         {(char *)"stereo-mode-v2",                                              MM_ATTRS_TYPE_INT,              MM_ATTRS_FLAG_RW, (void *)0},
146         {(char *)"metadata-source-v2",                                  MM_ATTRS_TYPE_STRING,   MM_ATTRS_FLAG_RW, (void *)NULL},
147         {(char *)"proj-type-v2",                                                MM_ATTRS_TYPE_INT,              MM_ATTRS_FLAG_RW, (void *)0},
148         {(char *)"pose-yaw-degrees-v2",                                 MM_ATTRS_TYPE_INT,              MM_ATTRS_FLAG_RW, (void *)0},
149         {(char *)"pose-pitch-degrees-v2",                               MM_ATTRS_TYPE_INT,              MM_ATTRS_FLAG_RW, (void *)0},
150         {(char *)"pose-roll-degrees-v2",                                MM_ATTRS_TYPE_INT,              MM_ATTRS_FLAG_RW, (void *)0},
151         {(char *)"cbmp-layout-v2",                                              MM_ATTRS_TYPE_INT,              MM_ATTRS_FLAG_RW, (void *)0},
152         {(char *)"cbmp-padding-v2",                                             MM_ATTRS_TYPE_INT,              MM_ATTRS_FLAG_RW, (void *)0},
153         {(char *)"equi-projection-bounds-top-v2",               MM_ATTRS_TYPE_INT,              MM_ATTRS_FLAG_RW, (void *)0},
154         {(char *)"equi-projection-bounds-bottom-v2",    MM_ATTRS_TYPE_INT,              MM_ATTRS_FLAG_RW, (void *)0},
155         {(char *)"equi-projection-bounds-left-v2",              MM_ATTRS_TYPE_INT,              MM_ATTRS_FLAG_RW, (void *)0},
156         {(char *)"equi-projection-bounds-right-v2",             MM_ATTRS_TYPE_INT,              MM_ATTRS_FLAG_RW, (void *)0},
157 };
158
159 static MMAttrsConstructInfo g_content_attrs[] = {
160         {(char *)"content-duration",                    MM_ATTRS_TYPE_INT,              MM_ATTRS_FLAG_RW, (void *)0},
161         {(char *)"content-video-codec",         MM_ATTRS_TYPE_INT,              MM_ATTRS_FLAG_RW, (void *)0},
162         {(char *)"content-video-format",                MM_ATTRS_TYPE_INT,              MM_ATTRS_FLAG_RW, (void *)0},
163         {(char *)"content-video-bitrate",               MM_ATTRS_TYPE_INT,              MM_ATTRS_FLAG_RW, (void *)0},
164         {(char *)"content-video-fps",                   MM_ATTRS_TYPE_INT,              MM_ATTRS_FLAG_RW, (void *)0},
165         {(char *)"content-video-width",         MM_ATTRS_TYPE_INT,              MM_ATTRS_FLAG_RW, (void *)0},
166         {(char *)"content-video-height",                MM_ATTRS_TYPE_INT,              MM_ATTRS_FLAG_RW, (void *)0},
167         {(char *)"content-video-thumbnail",             MM_ATTRS_TYPE_DATA,     MM_ATTRS_FLAG_RW, (void *)NULL},
168         {(char *)"content-video-track-index",   MM_ATTRS_TYPE_INT,              MM_ATTRS_FLAG_RW, (void *)0},
169         {(char *)"content-video-track-count",   MM_ATTRS_TYPE_INT,              MM_ATTRS_FLAG_RW, (void *)0},
170         {(char *)"content-audio-codec",         MM_ATTRS_TYPE_INT,              MM_ATTRS_FLAG_RW, (void *)0},
171         {(char *)"content-audio-bitrate",               MM_ATTRS_TYPE_INT,              MM_ATTRS_FLAG_RW, (void *)0},
172         {(char *)"content-audio-channels",              MM_ATTRS_TYPE_INT,              MM_ATTRS_FLAG_RW, (void *)0},
173         {(char *)"content-audio-samplerate",    MM_ATTRS_TYPE_INT,              MM_ATTRS_FLAG_RW, (void *)0},
174         {(char *)"content-audio-track-index",   MM_ATTRS_TYPE_INT,              MM_ATTRS_FLAG_RW, (void *)0},
175         {(char *)"content-audio-track-count",   MM_ATTRS_TYPE_INT,              MM_ATTRS_FLAG_RW, (void *)0},
176         {(char *)"content-audio-bitpersample",  MM_ATTRS_TYPE_INT,              MM_ATTRS_FLAG_RW, (void *)0},
177 };
178
179 #ifdef __MMFILE_DYN_LOADING__
180 #define MMFILE_FORMAT_SO_FILE_NAME  LIBDIR"/libmmfile_formats.so"
181 #define MMFILE_CODEC_SO_FILE_NAME   LIBDIR"/libmmfile_codecs.so"
182
183 static int (*mmfile_format_open)(MMFileFormatContext **formatContext, MMFileSourceType *fileSrc);
184 static int (*mmfile_format_read_stream)(MMFileFormatContext *formatContext);
185 static int (*mmfile_format_read_frame)(MMFileFormatContext *formatContext, unsigned int timestamp, MMFileFormatFrame *frame);
186 static int (*mmfile_format_read_tag)(MMFileFormatContext *formatContext);
187 static int (*mmfile_format_close)(MMFileFormatContext *formatContext);
188 static int (*mmfile_codec_open)(MMFileCodecContext **codecContext, int codecType, int codecId, MMFileCodecFrame *input);
189 static int (*mmfile_codec_decode)(MMFileCodecContext *codecContext, MMFileCodecFrame *output);
190 static int (*mmfile_codec_close)(MMFileCodecContext *codecContext);
191 static int (*mmfile_format_get_frame)(const char *path, double timestamp, bool is_accurate, unsigned char **frame, int *size, int *width, int *height);
192 static int (*mmfile_format_get_frame_from_memory)(const void *data, unsigned int datasize, double timestamp, bool is_accurate, unsigned char **frame, int *size, int *width, int *height);
193 #endif
194
195 #ifdef __MMFILE_DYN_LOADING__
196 static int _load_dynamic_functions(MMFILE_FUNC_HANDLE *pHandle)
197 {
198 /*      static int dll_func_initialized = 0; //disabled */
199
200         int ret = 0;
201
202         /* Get from function argument */
203         void *formatFuncHandle = NULL;
204         void *codecFuncHandle = NULL;
205
206         /* disabled
207         if (dll_func_initialized) {
208                 return 1;
209         }
210         */
211
212         formatFuncHandle = dlopen(MMFILE_FORMAT_SO_FILE_NAME, RTLD_LAZY);
213         if (!formatFuncHandle) {
214                 debug_error(DEBUG, "error: %s %s\n", "libmmfile_formats.so open error", dlerror());
215                 ret = 0;
216                 goto exception;
217         }
218
219         mmfile_format_open                      = dlsym(formatFuncHandle, "mmfile_format_open");
220         mmfile_format_read_stream       = dlsym(formatFuncHandle, "mmfile_format_read_stream");
221         mmfile_format_read_frame        = dlsym(formatFuncHandle, "mmfile_format_read_frame");
222         mmfile_format_read_tag          = dlsym(formatFuncHandle, "mmfile_format_read_tag");
223         mmfile_format_close                     = dlsym(formatFuncHandle, "mmfile_format_close");
224
225         if (!mmfile_format_open ||
226             !mmfile_format_read_stream ||
227             !mmfile_format_read_frame ||
228             !mmfile_format_read_tag ||
229             !mmfile_format_close) {
230
231                 debug_error(DEBUG, "error: %s\n", "format function load error");
232                 ret = 0;
233                 goto exception;
234         }
235
236         /*closed at app termination.*/
237         /*dlclose (formatFuncHandle); */
238
239         codecFuncHandle = dlopen(MMFILE_CODEC_SO_FILE_NAME, RTLD_LAZY | RTLD_GLOBAL);
240         if (!codecFuncHandle) {
241                 debug_error(DEBUG, "error: %s\n", "libmmfile_codecs.so open error");
242                 ret = 0;
243                 goto exception;
244         }
245
246         mmfile_codec_open               = dlsym(codecFuncHandle, "mmfile_codec_open");
247         mmfile_codec_decode     = dlsym(codecFuncHandle, "mmfile_codec_decode");
248         mmfile_codec_close              = dlsym(codecFuncHandle, "mmfile_codec_close");
249
250         if (!mmfile_codec_open || !mmfile_codec_decode || !mmfile_codec_close) {
251                 debug_error(DEBUG, "error: %s\n", "codec function load error");
252                 ret = 0;
253                 goto exception;
254         }
255
256         /*closed at app termination.*/
257         /*dlclose (codecFuncHandle); */
258
259 /*      dll_func_initialized = 1; // disabled */
260
261         pHandle->codecFuncHandle = codecFuncHandle;
262         pHandle->formatFuncHandle = formatFuncHandle;
263
264         return 1;
265
266 exception:
267         if (formatFuncHandle)
268                 dlclose(formatFuncHandle);
269
270         if (codecFuncHandle)
271                 dlclose(codecFuncHandle);
272
273         return ret;
274 }
275
276 static void _unload_dynamic_functions(MMFILE_FUNC_HANDLE *pHandle)
277 {
278         debug_fenter(RELEASE);
279
280         if (pHandle->formatFuncHandle)
281                 dlclose(pHandle->formatFuncHandle);
282
283         if (pHandle->codecFuncHandle)
284                 dlclose(pHandle->codecFuncHandle);
285
286         debug_fleave(RELEASE);
287 }
288
289 #endif /* __MMFILE_DYN_LOADING__ */
290
291 /**
292  * local functions.
293  */
294 static int _is_file_readable(const char *filename)
295 {
296         mm_file_retvm_if_fails(DEBUG, filename, FILEINFO_ERROR_INVALID_ARGUMENT);
297
298         if (access(filename, R_OK) == -1) {
299                 if (errno == EACCES || errno == EPERM) {
300                         debug_error(DEBUG, "Permission denied [%s]", filename);
301                         return FILEINFO_ERROR_PERMISSION_DENIED;
302                 } else {
303                         debug_error(DEBUG, "Not exist file [%s]", filename);
304                         return FILEINFO_ERROR_FILE_NOT_FOUND;
305                 }
306         }
307
308         return FILEINFO_ERROR_NONE;
309 }
310
311 static int _info_set_attr_media(MMHandleType attrs, MMFileFormatContext *formatContext)
312 {
313         int ret = 0;
314
315         if (formatContext->commandType == MM_FILE_TAG) {
316                 mm_attrs_set_string_by_name(attrs, MM_FILE_TAG_TITLE, formatContext->title);
317                 mm_attrs_set_string_by_name(attrs, MM_FILE_TAG_ARTIST, formatContext->artist);
318                 if (formatContext->author)
319                         mm_attrs_set_string_by_name(attrs, MM_FILE_TAG_AUTHOR, formatContext->author);
320                 else
321                         mm_attrs_set_string_by_name(attrs, MM_FILE_TAG_AUTHOR, formatContext->composer);
322                 mm_attrs_set_string_by_name(attrs, MM_FILE_TAG_ALBUM, formatContext->album);
323                 mm_attrs_set_string_by_name(attrs, MM_FILE_TAG_ALBUM_ARTIST, formatContext->album_artist);
324                 mm_attrs_set_string_by_name(attrs, MM_FILE_TAG_COPYRIGHT, formatContext->copyright);
325                 mm_attrs_set_string_by_name(attrs, MM_FILE_TAG_DESCRIPTION, formatContext->description);
326                 mm_attrs_set_string_by_name(attrs, MM_FILE_TAG_COMMENT, formatContext->comment);
327                 mm_attrs_set_string_by_name(attrs, MM_FILE_TAG_GENRE, formatContext->genre);
328                 mm_attrs_set_string_by_name(attrs, MM_FILE_TAG_CLASSIFICATION, formatContext->classification);
329                 mm_attrs_set_string_by_name(attrs, MM_FILE_TAG_DATE, formatContext->year);
330                 mm_attrs_set_string_by_name(attrs, MM_FILE_TAG_TRACK_NUM, formatContext->tagTrackNum);
331                 mm_attrs_set_string_by_name(attrs, MM_FILE_TAG_RATING, formatContext->rating);
332                 mm_attrs_set_string_by_name(attrs, MM_FILE_TAG_CONDUCTOR, formatContext->conductor);
333                 mm_attrs_set_string_by_name(attrs, MM_FILE_TAG_RECDATE, formatContext->recDate);
334                 mm_attrs_set_string_by_name(attrs, MM_FILE_TAG_POS, formatContext->part_of_set);
335
336                 mm_attrs_set_string_by_name(attrs, MM_FILE_TAG_ROTATE, formatContext->rotate);
337                 mm_attrs_set_double_by_name(attrs, MM_FILE_TAG_LONGITUDE, formatContext->longitude);
338                 mm_attrs_set_double_by_name(attrs, MM_FILE_TAG_LATIDUE, formatContext->latitude);
339                 mm_attrs_set_double_by_name(attrs, MM_FILE_TAG_ALTIDUE, formatContext->altitude);
340                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_SYNCLYRICS_NUM, formatContext->syncLyricsNum);
341                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_CDIS, formatContext->cdis);
342                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_SMTA, formatContext->smta);
343
344                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_SPHERICAL, formatContext->isSpherical);
345                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_SPHERICAL_STITCHED, formatContext->isStitched);
346                 mm_attrs_set_string_by_name(attrs, MM_FILE_TAG_SPHERICAL_STITCHING_SOFTWARE, formatContext->stitchingSoftware);
347                 mm_attrs_set_string_by_name(attrs, MM_FILE_TAG_SPHERICAL_PROJECTION_TYPE, formatContext->projectionType);
348                 mm_attrs_set_string_by_name(attrs, MM_FILE_TAG_SPHERICAL_STEREO_MODE, formatContext->stereoMode);
349                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_SPHERICAL_SOURCE_COUNT, formatContext->sourceCount);
350                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_SPHERICAL_INIT_VIEW_HEADING, formatContext->initViewHeading);
351                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_SPHERICAL_INIT_VIEW_PITCH, formatContext->initViewPitch);
352                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_SPHERICAL_INIT_VIEW_ROLL, formatContext->initViewRoll);
353                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_SPHERICAL_TIMESTAMP, formatContext->timestamp);
354                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_SPHERICAL_FULL_PANO_WIDTH, formatContext->fullPanoWidth);
355                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_SPHERICAL_FULL_PANO_HEIGHT, formatContext->fullPanoHeight);
356                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_SPHERICAL_CROPPED_AREA_IMAGE_WIDTH, formatContext->croppedAreaImageWidth);
357                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_SPHERICAL_CROPPED_AREA_IMAGE_HEIGHT, formatContext->croppedAreaImageHeight);
358                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_SPHERICAL_CROPPED_AREA_LEFT, formatContext->croppedAreaLeft);
359                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_SPHERICAL_CROPPED_AREA_TOP, formatContext->croppedAreaTop);
360
361                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_AMBISONIC_TYPE, formatContext->ambisonicType);
362                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_AMBISONIC_FORMAT, formatContext->ambisonicFormat);
363                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_AMBISONIC_ORDER, formatContext->ambisonicOrder);
364
365                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_SPHERICAL_V2_STEREO_MODE, formatContext->stereoModeV2);
366                 mm_attrs_set_string_by_name(attrs, MM_FILE_TAG_SPHERICAL_V2_METADATA_SOURCE, formatContext->metadataSourceV2);
367                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_SPHERICAL_V2_PROJ_TYPE, formatContext->projTypeV2);
368                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_SPHERICAL_V2_POSE_YAW, formatContext->poseYawV2);
369                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_SPHERICAL_V2_POSE_PITCH, formatContext->posePitchV2);
370                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_SPHERICAL_V2_POSE_ROLL, formatContext->poseRollV2);
371                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_SPHERICAL_V2_CBMP_LAYOUT, formatContext->cbmpLayoutV2);
372                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_SPHERICAL_V2_CBMP_PADDING, formatContext->cbmpPaddingV2);
373                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_SPHERICAL_V2_EQUI_BOUNDS_TOP, formatContext->equiBoundsTopV2);
374                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_SPHERICAL_V2_EQUI_BOUNDS_BOTTOM, formatContext->equiBoundsBottomV2);
375                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_SPHERICAL_V2_EQUI_BOUNDS_LEFT, formatContext->equiBoundsLeftV2);
376                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_SPHERICAL_V2_EQUI_BOUNDS_RIGHT, formatContext->equiBoundsRightV2);
377
378                 mm_attrs_set_data_by_name(attrs, MM_FILE_TAG_SYNCLYRICS, formatContext->syncLyrics, formatContext->syncLyricsNum);
379
380                 mm_attrs_set_string_by_name(attrs, MM_FILE_TAG_UNSYNCLYRICS, formatContext->unsyncLyrics);
381
382                 if (formatContext->artwork && formatContext->artworkSize > 0) {
383                         void *artworkCopy = NULL;
384                         artworkCopy = mmfile_malloc((formatContext->artworkSize));
385                         if (artworkCopy) {
386                                 memcpy(artworkCopy, formatContext->artwork, formatContext->artworkSize);
387                                 mm_attrs_set_data_by_name(attrs, MM_FILE_TAG_ARTWORK, artworkCopy, formatContext->artworkSize);
388                                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_ARTWORK_SIZE, formatContext->artworkSize);
389                                 mm_attrs_set_string_by_name(attrs, MM_FILE_TAG_ARTWORK_MIME, formatContext->artworkMime);
390                         }
391                 }
392         } else if (formatContext->commandType == MM_FILE_CONTENTS) {
393                 /*get duration*/
394                 mm_attrs_set_int_by_name(attrs, MM_FILE_CONTENT_DURATION, formatContext->duration);
395                 mm_attrs_set_int_by_name(attrs, MM_FILE_CONTENT_AUDIO_TRACK_COUNT, formatContext->audioTotalTrackNum);
396                 mm_attrs_set_int_by_name(attrs, MM_FILE_CONTENT_VIDEO_TRACK_COUNT, formatContext->videoTotalTrackNum);
397
398                 if (formatContext->videoTotalTrackNum > 0 &&
399                     formatContext->nbStreams > 0 &&
400                     formatContext->streams[MMFILE_VIDEO_STREAM]) {
401
402                         MMFileFormatStream *videoStream = formatContext->streams[MMFILE_VIDEO_STREAM];
403
404                         mm_attrs_set_int_by_name(attrs, MM_FILE_CONTENT_VIDEO_FORMAT, formatContext->formatType);
405                         mm_attrs_set_int_by_name(attrs, MM_FILE_CONTENT_VIDEO_CODEC, videoStream->codecId);
406                         mm_attrs_set_int_by_name(attrs, MM_FILE_CONTENT_VIDEO_BITRATE, videoStream->bitRate);
407                         mm_attrs_set_int_by_name(attrs, MM_FILE_CONTENT_VIDEO_FPS, videoStream->framePerSec);
408                         mm_attrs_set_int_by_name(attrs, MM_FILE_CONTENT_VIDEO_WIDTH, videoStream->width);
409                         mm_attrs_set_int_by_name(attrs, MM_FILE_CONTENT_VIDEO_HEIGHT, videoStream->height);
410
411                         if (formatContext->thumbNail && formatContext->thumbNail->frameData) {
412                                 void *thumbNailCopy = NULL;
413                                 thumbNailCopy = mmfile_malloc(formatContext->thumbNail->frameSize);
414
415                                 if (thumbNailCopy) {
416                                         memcpy(thumbNailCopy, formatContext->thumbNail->frameData, formatContext->thumbNail->frameSize);
417                                         mm_attrs_set_data_by_name(attrs, MM_FILE_CONTENT_VIDEO_THUMBNAIL, thumbNailCopy, formatContext->thumbNail->frameSize);
418                                         mm_attrs_set_int_by_name(attrs, MM_FILE_CONTENT_VIDEO_WIDTH, formatContext->thumbNail->frameWidth);
419                                         mm_attrs_set_int_by_name(attrs, MM_FILE_CONTENT_VIDEO_HEIGHT, formatContext->thumbNail->frameHeight);
420                                 }
421                         }
422                 }
423
424                 if (formatContext->audioTotalTrackNum > 0 &&
425                     formatContext->nbStreams > 0 &&
426                     formatContext->streams[MMFILE_AUDIO_STREAM]) {
427
428                         MMFileFormatStream *audioStream = formatContext->streams[MMFILE_AUDIO_STREAM];
429
430                         mm_attrs_set_int_by_name(attrs, MM_FILE_CONTENT_AUDIO_CODEC, audioStream->codecId);
431                         mm_attrs_set_int_by_name(attrs, MM_FILE_CONTENT_AUDIO_CHANNELS, audioStream->nbChannel);
432                         mm_attrs_set_int_by_name(attrs, MM_FILE_CONTENT_AUDIO_BITRATE, audioStream->bitRate);
433                         mm_attrs_set_int_by_name(attrs, MM_FILE_CONTENT_AUDIO_SAMPLERATE, audioStream->samplePerSec);
434                         mm_attrs_set_int_by_name(attrs, MM_FILE_CONTENT_AUDIO_BITPERSAMPLE, audioStream->bitPerSample);
435                 }
436         } else {
437                 ret = -1;
438         }
439
440         /*commit attrs*/
441         mm_attrs_commit_all(attrs);
442
443         return ret;
444 }
445
446 /**
447  * @param       frameContext    [in]    frame for decoding.
448  * @param       videoStream             [in]    information of video codec for frameContext.
449  * @param       decodedFrame    [inout] frame after decoding frameContext.
450  */
451 static int __decode_contents_frame(MMFileFormatFrame *frameContext, MMFileFormatStream *videoStream, MMFileCodecFrame *decodedFrame)
452 {
453         int ret = FILEINFO_ERROR_NONE;
454         MMFileCodecContext *codecContext = NULL;
455         MMFileCodecFrame codecFrame = {0, };
456
457         mm_file_retvm_if_fails(DEBUG, frameContext, FILEINFO_ERROR_FILE_INTERNAL);
458         mm_file_retvm_if_fails(DEBUG, videoStream, FILEINFO_ERROR_FILE_INTERNAL);
459         mm_file_retvm_if_fails(DEBUG, decodedFrame, FILEINFO_ERROR_FILE_INTERNAL);
460
461         codecFrame.frameDataSize = frameContext->frameSize;
462         codecFrame.width = frameContext->frameWidth;
463         codecFrame.height = frameContext->frameHeight;
464         codecFrame.frameData = frameContext->frameData;
465         codecFrame.configLen = frameContext->configLenth;
466         codecFrame.configData = frameContext->configData;
467         codecFrame.version = videoStream->version;
468
469         if (MMFILE_FORMAT_FAIL == mmfile_codec_open(&codecContext, MMFILE_VIDEO_DECODE, videoStream->codecId, &codecFrame)) {
470                 debug_error(DEBUG, "error: mmfile_codec_open\n");
471                 mmfile_codec_close(codecContext);
472                 return FILEINFO_ERROR_FILE_INTERNAL;
473         }
474
475         if (MMFILE_FORMAT_FAIL == mmfile_codec_decode(codecContext, decodedFrame)) {
476                 debug_error(DEBUG, "error: mmfile_codec_decode\n");
477                 ret = FILEINFO_ERROR_FILE_INTERNAL;
478         }
479
480         mmfile_codec_close(codecContext);
481
482         return ret;
483 }
484
485 static int
486 __get_contents_thumbnail(MMFileFormatContext *formatContext)
487 {
488         int ret = FILEINFO_ERROR_NONE;
489         MMFileFormatFrame frameContext = {0, };
490         MMFileCodecFrame decodedFrame = {0, };
491         MMFileFormatFrame *thumbnail = NULL;
492
493         mm_file_retvm_if_fails(DEBUG, formatContext, FILEINFO_ERROR_FILE_INTERNAL);
494
495         if (MMFILE_FORMAT_FAIL == mmfile_format_read_frame(formatContext, _SEEK_POINT_, &frameContext)) {
496                 debug_error(DEBUG, "error: mmfile_format_read_frame\n");
497                 ret = FILEINFO_ERROR_FILE_INTERNAL;
498                 goto exception;
499         }
500
501         /* set video thumbnail */
502         thumbnail = mmfile_malloc(sizeof(MMFileFormatFrame));
503         if (!thumbnail) {
504                 debug_error(DEBUG, "error: mmfile_malloc\n");
505                 ret = FILEINFO_ERROR_FILE_INTERNAL;
506                 goto exception;
507         }
508
509         if (frameContext.bCompressed) {
510                 ret = __decode_contents_frame(&frameContext, formatContext->streams[MMFILE_VIDEO_STREAM], &decodedFrame);
511                 if (FILEINFO_ERROR_NONE != ret) {
512                         debug_error(DEBUG, "error: __decode_contents_thumbnail\n");
513                         goto exception;
514                 }
515
516                 /* after decoding frameContext is done, it is no needed */
517                 mmfile_free(frameContext.frameData);
518                 mmfile_free(frameContext.configData);
519
520                 thumbnail->frameSize = decodedFrame.frameDataSize;
521                 thumbnail->frameWidth = decodedFrame.width;
522                 thumbnail->frameHeight = decodedFrame.height;
523                 thumbnail->frameData = decodedFrame.frameData;
524                 thumbnail->configLenth = 0;
525                 thumbnail->configData = NULL;
526         } else {
527                 thumbnail->frameSize = frameContext.frameSize;
528                 thumbnail->frameWidth = frameContext.frameWidth;
529                 thumbnail->frameHeight = frameContext.frameHeight;
530                 thumbnail->frameData = frameContext.frameData;
531                 thumbnail->configLenth = 0;
532                 thumbnail->configData = NULL;
533         }
534
535 #ifdef __MMFILE_TEST_MODE__
536         mmfile_format_print_frame(thumbnail);
537 #endif
538
539         formatContext->thumbNail = thumbnail;
540
541         /* because #MMFILE_FORMAT_SUCCESS is different with #FILEINFO_ERROR_NONE */
542         return FILEINFO_ERROR_NONE;
543 exception:
544         if (frameContext.bCompressed) {
545                 mmfile_free(decodedFrame.frameData);
546                 mmfile_free(decodedFrame.configData);
547         }
548
549         mmfile_free(thumbnail);
550         mmfile_free(frameContext.frameData);
551         mmfile_free(frameContext.configData);
552
553         return ret;
554 }
555
556 static int
557 _get_contents_info(MMHandleType attrs, MMFileSourceType *src, MMFILE_PARSE_INFO *parse)
558 {
559         MMFileFormatContext *formatContext = NULL;
560         int ret = 0;
561
562         mm_file_retvm_if_fails(DEBUG, src, FILEINFO_ERROR_FILE_INTERNAL);
563         mm_file_retvm_if_fails(DEBUG, parse, FILEINFO_ERROR_FILE_INTERNAL);
564
565         if (MMFILE_FORMAT_FAIL == mmfile_format_open(&formatContext, src) || formatContext == NULL) {
566                 debug_error(DEBUG, "error: mmfile_format_open\n");
567                 ret = FILEINFO_ERROR_FILE_INTERNAL;
568                 goto exception;
569         }
570
571         if (parse->type >= MM_FILE_PARSE_TYPE_NORMAL) {
572                 if (parse->type == MM_FILE_PARSE_TYPE_SAFE)
573                         formatContext->cdis = 1;
574
575                 if (MMFILE_FORMAT_FAIL == mmfile_format_read_stream(formatContext)) {
576                         debug_error(DEBUG, "error: mmfile_format_read_stream\n");
577                         ret = FILEINFO_ERROR_FILE_INTERNAL;
578                         goto exception;
579                 }
580
581                 parse->audio_track_num = formatContext->audioTotalTrackNum;
582                 parse->video_track_num = formatContext->videoTotalTrackNum;
583
584                 /* check uhqa content*/
585                 if (formatContext->streams[MMFILE_AUDIO_STREAM] != NULL)
586                         parse->is_uhqa = formatContext->streams[MMFILE_AUDIO_STREAM]->is_uhqa;
587                 else
588                         parse->is_uhqa = FALSE;
589
590                 if (parse->type >= MM_FILE_PARSE_TYPE_ALL && formatContext->videoTotalTrackNum > 0) {
591 /*why below code needed?
592 This API is for extracting some attributes not metadata(TAG). mm_file_create_content_attrs() use this API.
593 but MMFileUtilGetMetaDataFromMP4() Extract just TAG info. That is needed for mm_file_create_tag_attrs()*/
594 #if 0
595                         if (parse->type != MM_FILE_PARSE_TYPE_SAFE) {
596                                 if (formatContext->formatType == MM_FILE_FORMAT_3GP || formatContext->formatType == MM_FILE_FORMAT_MP4) {
597                                         MMFileUtilGetMetaDataFromMP4(formatContext);
598                                 }
599                         }
600 #endif
601                         ret = __get_contents_thumbnail(formatContext);
602                         if (FILEINFO_ERROR_NONE != ret) {
603                                 debug_error(DEBUG, "error: __get_contents_thumbnail\n");
604                                 ret = FILEINFO_ERROR_NONE;
605                         }
606                 }
607         } else {
608                 /**
609                  * if MM_FILE_PARSE_TYPE_SIMPLE, just get number of each stream.
610                  */
611                 parse->audio_track_num = formatContext->audioTotalTrackNum;
612                 parse->video_track_num = formatContext->videoTotalTrackNum;
613         }
614
615         formatContext->commandType = MM_FILE_CONTENTS;
616
617         if (parse->type >= MM_FILE_PARSE_TYPE_NORMAL)
618                 _info_set_attr_media(attrs, formatContext);
619
620         if (formatContext->thumbNail) {
621                 mmfile_free(formatContext->thumbNail->frameData);
622                 mmfile_free(formatContext->thumbNail->configData);
623                 mmfile_free(formatContext->thumbNail);
624         }
625
626 exception:
627         if (formatContext)
628                 mmfile_format_close(formatContext);
629
630         return ret;
631 }
632
633
634 static int
635 _get_tag_info(MMHandleType attrs, MMFileSourceType *src)
636 {
637         MMFileFormatContext *formatContext = NULL;
638         int ret = 0;
639
640         ret = mmfile_format_open(&formatContext, src);
641         if (MMFILE_FORMAT_FAIL == ret || formatContext == NULL) {
642                 debug_error(DEBUG, "error: mmfile_format_open\n");
643                 ret = FILEINFO_ERROR_FILE_INTERNAL;
644                 goto exception;
645         }
646
647         ret = mmfile_format_read_tag(formatContext);
648         if (MMFILE_FORMAT_FAIL == ret) {
649                 debug_warning(DEBUG, "reading tag is fail\n");
650                 ret = FILEINFO_ERROR_FILE_INTERNAL;
651                 goto exception;
652         }
653
654         formatContext->commandType = MM_FILE_TAG;
655
656         _info_set_attr_media(attrs, formatContext);
657
658         if (formatContext)  {
659                 mmfile_format_close(formatContext);
660         }
661
662         return FILEINFO_ERROR_NONE;
663
664
665 exception:
666         if (formatContext)  {
667                 mmfile_format_close(formatContext);
668         }
669
670         return FILEINFO_ERROR_FILE_INTERNAL;
671 }
672
673
674 /**
675  * global functions.
676  */
677 int mm_file_get_attrs(MMHandleType attrs, const char *first_attribute_name, ...)
678 {
679         int ret = FILEINFO_ERROR_NONE;
680         va_list var_args;
681         char *err_attr_name = NULL;
682
683         mm_file_retvm_if_fails(DEBUG, attrs, FILEINFO_ERROR_INVALID_ARGUMENT);
684         mm_file_retvm_if_fails(DEBUG, first_attribute_name, FILEINFO_ERROR_INVALID_ARGUMENT);
685
686         /* get requested attributes */
687         va_start(var_args, first_attribute_name);
688         ret = mm_attrs_get_valist(attrs, &err_attr_name, first_attribute_name, var_args);
689         va_end(var_args);
690
691         if (ret != FILEINFO_ERROR_NONE) {
692                 if (err_attr_name) {
693                         debug_error(DEBUG, "failed to get %s\n", err_attr_name);
694                         free(err_attr_name);
695                 }
696         }
697
698         return ret;
699 }
700
701 int mm_file_get_synclyrics_info(MMHandleType tag_attrs, int index, unsigned long *time_info, char **lyrics)
702 {
703         int ret = FILEINFO_ERROR_NONE;
704         AvSynclyricsInfo *sync_lyric_item = NULL;
705         GList *synclyrics_list = NULL;
706
707         debug_fenter(RELEASE);
708
709         mm_file_retvm_if_fails(DEBUG, tag_attrs, FILEINFO_ERROR_INVALID_ARGUMENT);
710
711         ret = mm_attrs_get_data_by_name(tag_attrs, MM_FILE_TAG_SYNCLYRICS, (void **)&synclyrics_list);
712         if (ret != FILEINFO_ERROR_NONE) {
713                 debug_warning(RELEASE, "get data fail");
714                 return ret;
715         }
716
717         mm_file_retvm_if_fails(RELEASE, synclyrics_list, FILEINFO_ERROR_ATTR_NOT_EXIST);
718
719         sync_lyric_item = (AvSynclyricsInfo *)g_list_nth_data(synclyrics_list, index);
720
721         mm_file_retvm_if_fails(RELEASE, sync_lyric_item, FILEINFO_ERROR_ATTR_NOT_EXIST);
722
723         *time_info = sync_lyric_item->time_info;
724         *lyrics = sync_lyric_item->lyric_info;
725
726         return ret;
727 }
728
729 int mm_file_create_tag_attrs(MMHandleType *tag_attrs, const char *filename)
730 {
731         int ret = FILEINFO_ERROR_NONE;
732         MMHandleType attrs = NULL;
733         MMFileSourceType src;
734
735         debug_fenter(RELEASE);
736
737         mm_file_retvm_if_fails(DEBUG, tag_attrs, FILEINFO_ERROR_INVALID_ARGUMENT);
738
739         ret = _is_file_readable(filename);
740         if (ret != FILEINFO_ERROR_NONE)
741                 return ret;
742
743 #ifdef __MMFILE_DYN_LOADING__
744         MMFILE_FUNC_HANDLE func_handle;
745
746         ret = _load_dynamic_functions(&func_handle);
747         if (ret == 0) {
748                 debug_error(DEBUG, "load library error\n");
749                 return FILEINFO_ERROR_FILE_INTERNAL;
750         }
751 #endif
752
753         /*set source file infomation*/
754         MM_FILE_SET_MEDIA_FILE_SRC(src, filename);
755
756         /*set attrs*/
757         ret = mm_attrs_new(g_tag_attrs, ARRAY_SIZE(g_tag_attrs), "tag", NULL, NULL, &attrs);
758         if (ret) {
759                 debug_error(DEBUG, "attribute internal error.\n");
760                 ret = FILEINFO_ERROR_FILE_INTERNAL;
761                 goto END;
762         }
763
764         ret = _get_tag_info(attrs, &src);
765         if (ret != FILEINFO_ERROR_NONE) {
766                 mm_attrs_free(attrs);
767                 attrs = NULL;
768                 debug_error(DEBUG, "failed to get tag: %s\n", filename);
769         }
770
771         *tag_attrs = attrs;
772
773 END:
774 #ifdef __MMFILE_DYN_LOADING__
775         _unload_dynamic_functions(&func_handle);
776 #endif
777
778         debug_fleave(RELEASE);
779
780         return ret;
781 }
782
783
784 EXPORT_API
785 int mm_file_destroy_tag_attrs(MMHandleType tag_attrs)
786 {
787         void *artwork = NULL;
788         GList *synclyrics_list = NULL;
789         int ret = FILEINFO_ERROR_NONE;
790
791         debug_fenter(RELEASE);
792
793         mm_file_retvm_if_fails(DEBUG, tag_attrs, FILEINFO_ERROR_INVALID_ARGUMENT);
794
795         ret = mm_attrs_get_data_by_name(tag_attrs, MM_FILE_TAG_ARTWORK, &artwork);
796         mmfile_free(artwork);
797
798         ret = mm_attrs_get_data_by_name(tag_attrs, MM_FILE_TAG_SYNCLYRICS, (void **)&synclyrics_list);
799         mm_file_free_synclyrics_list(synclyrics_list);
800         mm_attrs_free(tag_attrs);
801
802         debug_fleave(RELEASE);
803
804         return ret;
805 }
806
807 static int __create_content_attrs(MMHandleType *contents_attrs, const char *filename, MMFILE_PARSE_TYPE parse_type)
808 {
809         MMHandleType attrs = NULL;
810         MMFileSourceType src = {0, };
811         MMFILE_PARSE_INFO parse = {0, };
812         int ret = 0;
813
814         debug_fenter(RELEASE);
815
816         mm_file_retvm_if_fails(DEBUG, contents_attrs, FILEINFO_ERROR_INVALID_ARGUMENT);
817
818         ret = _is_file_readable(filename);
819         if (ret != FILEINFO_ERROR_NONE)
820                 return ret;
821
822 #ifdef __MMFILE_DYN_LOADING__
823         MMFILE_FUNC_HANDLE func_handle;
824
825 #ifdef CHECK_TIME
826         int64_t ti;
827         ti = gettime();
828 #endif
829
830         ret = _load_dynamic_functions(&func_handle);
831         if (ret == 0) {
832                 debug_error(DEBUG, "load library error\n");
833                 return FILEINFO_ERROR_FILE_INTERNAL;
834         }
835
836 #ifdef CHECK_TIME
837         debug_msg(DEBUG, "_load_dynamic_functions() = %lld\n", gettime() - ti);
838 #endif
839
840 #endif
841
842         /*set source file infomation*/
843         MM_FILE_SET_MEDIA_FILE_SRC(src, filename);
844
845         /*set attrs*/
846         ret = mm_attrs_new(g_content_attrs, ARRAY_SIZE(g_content_attrs), "content", NULL, NULL, &attrs);
847         if (ret) {
848                 debug_error(DEBUG, "attribute internal error.\n");
849                 ret = FILEINFO_ERROR_FILE_INTERNAL;
850                 goto END;
851         }
852
853
854         parse.type = parse_type;
855         ret = _get_contents_info(attrs, &src, &parse);
856         if (ret != FILEINFO_ERROR_NONE) {
857                 mm_attrs_free(attrs);
858                 attrs = NULL;
859                 debug_error(DEBUG, "failed to get contents: %s\n", filename);
860         }
861
862         *contents_attrs = attrs;
863
864
865 END:
866 #ifdef __MMFILE_DYN_LOADING__
867
868 #ifdef CHECK_TIME
869         ti = gettime();
870 #endif
871
872         _unload_dynamic_functions(&func_handle);
873
874 #ifdef CHECK_TIME
875         debug_msg(DEBUG, "_unload_dynamic_functions() = %lld\n", gettime() - ti);
876 #endif
877
878 #endif
879
880         debug_fleave(RELEASE);
881
882         return ret;
883 }
884
885 EXPORT_API
886 int mm_file_create_content_attrs(MMHandleType *contents_attrs, const char *filename)
887 {
888         return __create_content_attrs(contents_attrs, filename, MM_FILE_PARSE_TYPE_ALL);
889 }
890
891 EXPORT_API
892 int mm_file_create_tag_attrs_from_memory(MMHandleType *tag_attrs, const void *data, unsigned int size, int format)
893 {
894         MMHandleType attrs = NULL;
895         MMFileSourceType src;
896         /*MMFILE_PARSE_INFO parse = {0, };*/
897         int ret = 0;
898
899         debug_fenter(RELEASE);
900
901         mm_file_retvm_if_fails(DEBUG, tag_attrs, FILEINFO_ERROR_INVALID_ARGUMENT);
902         mm_file_retvm_if_fails(DEBUG, data, FILEINFO_ERROR_INVALID_ARGUMENT);
903
904 #ifdef __MMFILE_DYN_LOADING__
905         MMFILE_FUNC_HANDLE func_handle;
906
907         ret = _load_dynamic_functions(&func_handle);
908         if (ret == 0) {
909                 debug_error(DEBUG, "load library error\n");
910                 return FILEINFO_ERROR_FILE_INTERNAL;
911         }
912 #endif
913
914         MM_FILE_SET_MEDIA_MEM_SRC(src, data, size, format);
915
916         /*set attrs*/
917         ret = mm_attrs_new(g_tag_attrs, ARRAY_SIZE(g_tag_attrs), "tag", NULL, NULL, &attrs);
918         if (ret) {
919                 debug_error(DEBUG, "attribute internal error.\n");
920                 ret = FILEINFO_ERROR_FILE_INTERNAL;
921                 goto END;
922         }
923
924         /*parse.type = MM_FILE_PARSE_TYPE_ALL;*/
925         ret = _get_tag_info(attrs, &src);
926         if (ret != FILEINFO_ERROR_NONE) {
927                 mm_attrs_free(attrs);
928                 attrs = NULL;
929                 debug_error(DEBUG, "failed to get tag");
930         }
931
932         *tag_attrs = attrs;
933
934 END:
935 #ifdef __MMFILE_DYN_LOADING__
936         _unload_dynamic_functions(&func_handle);
937 #endif
938
939         debug_fleave(RELEASE);
940
941         return ret;
942 }
943
944
945 EXPORT_API
946 int mm_file_create_content_attrs_from_memory(MMHandleType *contents_attrs, const void *data, unsigned int size, int format)
947 {
948         MMHandleType attrs = NULL;
949         MMFileSourceType src;
950         MMFILE_PARSE_INFO parse = {0, };
951         int ret = 0;
952
953         debug_fenter(RELEASE);
954
955         mm_file_retvm_if_fails(DEBUG, contents_attrs, FILEINFO_ERROR_INVALID_ARGUMENT);
956         mm_file_retvm_if_fails(DEBUG, data, FILEINFO_ERROR_INVALID_ARGUMENT);
957
958 #ifdef __MMFILE_DYN_LOADING__
959         MMFILE_FUNC_HANDLE func_handle;
960
961         ret = _load_dynamic_functions(&func_handle);
962         if (ret == 0) {
963                 debug_error(DEBUG, "load library error\n");
964                 return FILEINFO_ERROR_FILE_INTERNAL;
965         }
966 #endif
967
968         MM_FILE_SET_MEDIA_MEM_SRC(src, data, size, format);
969
970         /*set attrs*/
971         ret = mm_attrs_new(g_content_attrs, ARRAY_SIZE(g_content_attrs), "content", NULL, NULL, &attrs);
972         if (ret) {
973                 debug_error(DEBUG, "attribute internal error.\n");
974                 ret = FILEINFO_ERROR_FILE_INTERNAL;
975                 goto END;
976         }
977
978         parse.type = MM_FILE_PARSE_TYPE_ALL;
979         ret = _get_contents_info(attrs, &src, &parse);
980         if (ret != FILEINFO_ERROR_NONE) {
981                 mm_attrs_free(attrs);
982                 attrs = NULL;
983                 debug_error(DEBUG, "failed to get contents");
984         }
985
986         *contents_attrs = attrs;
987
988 END:
989 #ifdef __MMFILE_DYN_LOADING__
990         _unload_dynamic_functions(&func_handle);
991 #endif
992
993         debug_fleave(RELEASE);
994
995         return ret;
996 }
997
998
999 EXPORT_API
1000 int mm_file_destroy_content_attrs(MMHandleType contents_attrs)
1001 {
1002         void *thumbnail = NULL;
1003         int ret = FILEINFO_ERROR_NONE;
1004
1005         debug_fenter(RELEASE);
1006
1007         mm_file_retvm_if_fails(DEBUG, contents_attrs, FILEINFO_ERROR_INVALID_ARGUMENT);
1008
1009         ret = mm_attrs_get_data_by_name(contents_attrs, MM_FILE_CONTENT_VIDEO_THUMBNAIL, &thumbnail);
1010         mmfile_free(thumbnail);
1011
1012         mm_attrs_free(contents_attrs);
1013
1014         debug_fleave(RELEASE);
1015
1016         return ret;
1017 }
1018
1019
1020 EXPORT_API
1021 int mm_file_get_stream_info(const char *filename, int *audio_stream_num, int *video_stream_num)
1022 {
1023         MMFileSourceType     src = {0, };
1024         MMFILE_PARSE_INFO    parse = {0, };
1025
1026         int ret = 0;
1027
1028         debug_fenter(RELEASE);
1029
1030         mm_file_retvm_if_fails(DEBUG, audio_stream_num, FILEINFO_ERROR_INVALID_ARGUMENT);
1031         mm_file_retvm_if_fails(DEBUG, video_stream_num, FILEINFO_ERROR_INVALID_ARGUMENT);
1032
1033         ret = _is_file_readable(filename);
1034         if (ret != FILEINFO_ERROR_NONE)
1035                 return ret;
1036
1037 #ifdef __MMFILE_DYN_LOADING__
1038         MMFILE_FUNC_HANDLE func_handle;
1039
1040         ret = _load_dynamic_functions(&func_handle);
1041         if (ret == 0) {
1042                 debug_error(DEBUG, "load library error\n");
1043                 return FILEINFO_ERROR_FILE_INTERNAL;
1044         }
1045 #endif
1046
1047         /*set source file infomation*/
1048         MM_FILE_SET_MEDIA_FILE_SRC(src, filename);
1049
1050
1051         parse.type = MM_FILE_PARSE_TYPE_SIMPLE;
1052         ret = _get_contents_info(NULL, &src, &parse);
1053         if (ret != FILEINFO_ERROR_NONE) {
1054                 debug_error(DEBUG, "failed to get stream info: %s\n", filename);
1055         } else {
1056                 if (parse.audio_track_num == 0 && parse.video_track_num == 0) {
1057                         debug_error(DEBUG, "empty header. retry to get stream info: %s\n", filename);
1058                         parse.type = MM_FILE_PARSE_TYPE_NORMAL;
1059                         ret = _get_contents_info(NULL, &src, &parse);
1060                 }
1061         }
1062
1063         /*set number of each stream*/
1064         *audio_stream_num = parse.audio_track_num;
1065         *video_stream_num = parse.video_track_num;
1066
1067 #ifdef __MMFILE_DYN_LOADING__
1068         _unload_dynamic_functions(&func_handle);
1069 #endif
1070
1071         debug_fleave(RELEASE);
1072
1073         return ret;
1074 }
1075
1076 EXPORT_API
1077 int mm_file_create_content_attrs_simple(MMHandleType *contents_attrs, const char *filename)
1078 {
1079         return __create_content_attrs(contents_attrs, filename, MM_FILE_PARSE_TYPE_NORMAL);
1080 }
1081
1082 EXPORT_API
1083 int mm_file_create_content_attrs_safe(MMHandleType *contents_attrs, const char *filename)
1084 {
1085         return __create_content_attrs(contents_attrs, filename, MM_FILE_PARSE_TYPE_SAFE);
1086 }
1087
1088 EXPORT_API
1089 int mm_file_get_video_frame(const char *path, double timestamp, bool is_accurate, unsigned char **frame, int *size, int *width, int *height)
1090 {
1091         int ret = 0;
1092         void *formatFuncHandle = NULL;
1093
1094         mm_file_retvm_if_fails(DEBUG, path, FILEINFO_ERROR_INVALID_ARGUMENT);
1095
1096 #ifdef __MMFILE_DYN_LOADING__
1097         /* Get from function argument */
1098         formatFuncHandle = dlopen(MMFILE_FORMAT_SO_FILE_NAME, RTLD_LAZY);
1099         if (!formatFuncHandle) {
1100                 debug_error(DEBUG, "error : dlopen");
1101                 goto exception;
1102         }
1103
1104         mmfile_format_get_frame = dlsym(formatFuncHandle, "mmfile_format_get_frame");
1105         if (!mmfile_format_get_frame) {
1106                 debug_error(DEBUG, "error : load library");
1107                 goto exception;
1108         }
1109 #endif
1110
1111         debug_msg(RELEASE, "file path [%s] is_accurate [%d]", path, is_accurate);
1112
1113         ret = mmfile_format_get_frame(path, timestamp, is_accurate, frame, size, width, height);
1114         if (ret  == MMFILE_FORMAT_FAIL) {
1115                 debug_error(DEBUG, "error : get frame");
1116                 goto exception;
1117         }
1118
1119         if (formatFuncHandle)
1120                 dlclose(formatFuncHandle);
1121
1122         return FILEINFO_ERROR_NONE;
1123
1124 exception:
1125         if (formatFuncHandle)
1126                 dlclose(formatFuncHandle);
1127
1128         return FILEINFO_ERROR_FILE_INTERNAL;
1129 }
1130
1131 EXPORT_API
1132 int mm_file_get_video_frame_from_memory(const void *data, unsigned int datasize,  double timestamp, bool is_accurate, unsigned char **frame, int *size, int *width, int *height)
1133 {
1134         int ret = 0;
1135         void *formatFuncHandle = NULL;
1136
1137         mm_file_retvm_if_fails(DEBUG, data, FILEINFO_ERROR_INVALID_ARGUMENT);
1138         mm_file_retvm_if_fails(DEBUG, datasize != 0, FILEINFO_ERROR_INVALID_ARGUMENT);
1139
1140 #ifdef __MMFILE_DYN_LOADING__
1141         /* Get from function argument */
1142         formatFuncHandle = dlopen(MMFILE_FORMAT_SO_FILE_NAME, RTLD_LAZY);
1143         if (!formatFuncHandle) {
1144                 debug_error(DEBUG, "error : dlopen");
1145                 goto exception;
1146         }
1147
1148         mmfile_format_get_frame_from_memory = dlsym(formatFuncHandle, "mmfile_format_get_frame_from_memory");
1149         if (!mmfile_format_get_frame_from_memory) {
1150                 debug_error(DEBUG, "error : load library");
1151                 goto exception;
1152         }
1153 #endif
1154
1155         debug_msg(RELEASE, "data [%p], data_size[%d], is_accurate [%d]", data, datasize, is_accurate);
1156
1157         ret = mmfile_format_get_frame_from_memory(data, datasize, timestamp, is_accurate, frame, size, width, height);
1158         if (ret  == MMFILE_FORMAT_FAIL) {
1159                 debug_error(DEBUG, "error : get frame");
1160                 goto exception;
1161         }
1162
1163         if (formatFuncHandle)
1164                 dlclose(formatFuncHandle);
1165
1166         return FILEINFO_ERROR_NONE;
1167
1168 exception:
1169         if (formatFuncHandle)
1170                 dlclose(formatFuncHandle);
1171
1172         return FILEINFO_ERROR_FILE_INTERNAL;
1173 }
1174
1175 EXPORT_API
1176 int mm_file_check_uhqa(const char *filename, bool *is_uhqa)
1177 {
1178         MMHandleType attrs = NULL;
1179         MMFileSourceType src = {0, };
1180         MMFILE_PARSE_INFO parse = {0, };
1181         int ret = 0;
1182
1183         ret = _is_file_readable(filename);
1184         if (ret != FILEINFO_ERROR_NONE)
1185                 return ret;
1186
1187 #ifdef __MMFILE_DYN_LOADING__
1188         MMFILE_FUNC_HANDLE func_handle;
1189
1190         ret = _load_dynamic_functions(&func_handle);
1191         if (ret == 0) {
1192                 debug_error(DEBUG, "load library error\n");
1193                 return FILEINFO_ERROR_FILE_INTERNAL;
1194         }
1195 #endif
1196
1197         /*set source file infomation*/
1198         MM_FILE_SET_MEDIA_FILE_SRC(src, filename);
1199
1200         /*set attrs*/
1201         ret = mm_attrs_new(g_content_attrs, ARRAY_SIZE(g_content_attrs), "content", NULL, NULL, &attrs);
1202         if (ret) {
1203                 debug_error(DEBUG, "attribute internal error.\n");
1204                 ret = FILEINFO_ERROR_FILE_INTERNAL;
1205                 goto END;
1206         }
1207
1208         parse.type = MM_FILE_PARSE_TYPE_NORMAL;
1209         ret = _get_contents_info(attrs, &src, &parse);
1210         if (ret == FILEINFO_ERROR_NONE) {
1211                 *is_uhqa = parse.is_uhqa;
1212         } else {
1213                 debug_error(DEBUG, "_get_contents_info failed\n");
1214                 *is_uhqa = FALSE;
1215         }
1216
1217         mm_attrs_free(attrs);
1218
1219 END:
1220 #ifdef __MMFILE_DYN_LOADING__
1221         _unload_dynamic_functions(&func_handle);
1222 #endif
1223
1224         debug_fleave(RELEASE);
1225
1226         return ret;
1227 }