Support TPOS (Part of a Set)
[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 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 };
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 int (*mmfile_format_open)(MMFileFormatContext **formatContext, MMFileSourceType *fileSrc);
184 int (*mmfile_format_read_stream)(MMFileFormatContext *formatContext);
185 int (*mmfile_format_read_frame)(MMFileFormatContext *formatContext, unsigned int timestamp, MMFileFormatFrame *frame);
186 int (*mmfile_format_read_tag)(MMFileFormatContext *formatContext);
187 int (*mmfile_format_close)(MMFileFormatContext *formatContext);
188 int (*mmfile_codec_open)(MMFileCodecContext **codecContext, int codecType, int codecId, MMFileCodecFrame *input);
189 int (*mmfile_codec_decode)(MMFileCodecContext *codecContext, MMFileCodecFrame *output);
190 int (*mmfile_codec_close)(MMFileCodecContext *codecContext);
191 int (*mmfile_format_get_frame)(const char *path, double timestamp, bool is_accurate, unsigned char **frame, int *size, int *width, int *height);
192 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\n", "libmmfile_formats.so open error");
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) dlclose(formatFuncHandle);
268         if (codecFuncHandle)  dlclose(codecFuncHandle);
269
270         return ret;
271 }
272
273 static void _unload_dynamic_functions(MMFILE_FUNC_HANDLE *pHandle)
274 {
275         debug_fenter(RELEASE);
276
277         if (pHandle->formatFuncHandle) {
278                 dlclose(pHandle->formatFuncHandle);
279         }
280         if (pHandle->codecFuncHandle) {
281                 dlclose(pHandle->codecFuncHandle);
282         }
283
284         debug_fleave(RELEASE);
285 }
286
287
288 #endif /* __MMFILE_DYN_LOADING__ */
289
290 /**
291  * local functions.
292  */
293 static int
294 _is_file_exist(const char *filename)
295 {
296         int ret = FILEINFO_ERROR_NONE;
297         if (filename) {
298                 const char *to_access = (strstr(filename, "file://") != NULL) ? filename + 7 : filename;
299                 ret = access(to_access, R_OK);
300                 if (ret < 0) {
301                         if (errno == EACCES || errno == EPERM) {
302                                 debug_error(DEBUG, "Permission denied [%s]", to_access);
303                                 ret = FILEINFO_ERROR_PERMISSION_DENIED;
304                         } else {
305                                 debug_error(DEBUG, "Not exist file [%s]", to_access);
306                                 ret = FILEINFO_ERROR_FILE_NOT_FOUND;
307                         }
308                 }
309         }
310         return ret;
311 }
312
313 static int
314 _info_set_attr_media(MMHandleType attrs, MMFileFormatContext *formatContext)
315 {
316         int ret = 0;
317
318         if (formatContext->commandType == MM_FILE_TAG) {
319                 if (formatContext->title)                               mm_attrs_set_string_by_name(attrs, MM_FILE_TAG_TITLE, formatContext->title);
320                 if (formatContext->artist)                              mm_attrs_set_string_by_name(attrs, MM_FILE_TAG_ARTIST, formatContext->artist);
321                 if (formatContext->author)                      mm_attrs_set_string_by_name(attrs, MM_FILE_TAG_AUTHOR, formatContext->author);
322                 if (formatContext->composer && formatContext->author == NULL)
323                         mm_attrs_set_string_by_name(attrs, MM_FILE_TAG_AUTHOR, formatContext->composer);
324                 if (formatContext->album)                               mm_attrs_set_string_by_name(attrs, MM_FILE_TAG_ALBUM, formatContext->album);
325                 if (formatContext->album_artist)                                mm_attrs_set_string_by_name(attrs, MM_FILE_TAG_ALBUM_ARTIST, formatContext->album_artist);
326                 if (formatContext->copyright)                   mm_attrs_set_string_by_name(attrs, MM_FILE_TAG_COPYRIGHT, formatContext->copyright);
327                 if (formatContext->description)                 mm_attrs_set_string_by_name(attrs, MM_FILE_TAG_DESCRIPTION, formatContext->description);
328                 if (formatContext->comment)                     mm_attrs_set_string_by_name(attrs, MM_FILE_TAG_COMMENT, formatContext->comment);
329                 if (formatContext->genre)                               mm_attrs_set_string_by_name(attrs, MM_FILE_TAG_GENRE, formatContext->genre);
330                 if (formatContext->classification)              mm_attrs_set_string_by_name(attrs, MM_FILE_TAG_CLASSIFICATION, formatContext->classification);
331                 if (formatContext->year)                                mm_attrs_set_string_by_name(attrs, MM_FILE_TAG_DATE, formatContext->year);
332                 if (formatContext->tagTrackNum)         mm_attrs_set_string_by_name(attrs, MM_FILE_TAG_TRACK_NUM, formatContext->tagTrackNum);
333                 if (formatContext->rating)                              mm_attrs_set_string_by_name(attrs, MM_FILE_TAG_RATING, formatContext->rating);
334                 if (formatContext->conductor)                   mm_attrs_set_string_by_name(attrs, MM_FILE_TAG_CONDUCTOR, formatContext->conductor);
335                 if (formatContext->recDate)                     mm_attrs_set_string_by_name(attrs, MM_FILE_TAG_RECDATE, formatContext->recDate);
336                 if (formatContext->part_of_set)                 mm_attrs_set_string_by_name(attrs, MM_FILE_TAG_POS, formatContext->part_of_set);
337
338                 if (formatContext->rotate)                              mm_attrs_set_string_by_name(attrs, MM_FILE_TAG_ROTATE, formatContext->rotate);
339                 mm_attrs_set_double_by_name(attrs, MM_FILE_TAG_LONGITUDE, formatContext->longitude);
340                 mm_attrs_set_double_by_name(attrs, MM_FILE_TAG_LATIDUE, formatContext->latitude);
341                 mm_attrs_set_double_by_name(attrs, MM_FILE_TAG_ALTIDUE, formatContext->altitude);
342                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_SYNCLYRICS_NUM, formatContext->syncLyricsNum);
343                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_CDIS, formatContext->cdis);
344                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_SMTA, formatContext->smta);
345
346                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_SPHERICAL, formatContext->isSpherical);
347                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_SPHERICAL_STITCHED, formatContext->isStitched);
348                 if (formatContext->stitchingSoftware)   mm_attrs_set_string_by_name(attrs, MM_FILE_TAG_SPHERICAL_STITCHING_SOFTWARE, formatContext->stitchingSoftware);
349                 if (formatContext->projectionType)              mm_attrs_set_string_by_name(attrs, MM_FILE_TAG_SPHERICAL_PROJECTION_TYPE, formatContext->projectionType);
350                 if (formatContext->stereoMode)                  mm_attrs_set_string_by_name(attrs, MM_FILE_TAG_SPHERICAL_STEREO_MODE, formatContext->stereoMode);
351                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_SPHERICAL_SOURCE_COUNT, formatContext->sourceCount);
352                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_SPHERICAL_INIT_VIEW_HEADING, formatContext->initViewHeading);
353                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_SPHERICAL_INIT_VIEW_PITCH, formatContext->initViewPitch);
354                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_SPHERICAL_INIT_VIEW_ROLL, formatContext->initViewRoll);
355                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_SPHERICAL_TIMESTAMP, formatContext->timestamp);
356                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_SPHERICAL_FULL_PANO_WIDTH, formatContext->fullPanoWidth);
357                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_SPHERICAL_FULL_PANO_HEIGHT, formatContext->fullPanoHeight);
358                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_SPHERICAL_CROPPED_AREA_IMAGE_WIDTH, formatContext->croppedAreaImageWidth);
359                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_SPHERICAL_CROPPED_AREA_IMAGE_HEIGHT, formatContext->croppedAreaImageHeight);
360                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_SPHERICAL_CROPPED_AREA_LEFT, formatContext->croppedAreaLeft);
361                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_SPHERICAL_CROPPED_AREA_TOP, formatContext->croppedAreaTop);
362
363                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_AMBISONIC_TYPE, formatContext->ambisonicType);
364                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_AMBISONIC_FORMAT, formatContext->ambisonicFormat);
365                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_AMBISONIC_ORDER, formatContext->ambisonicOrder);
366
367                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_SPHERICAL_V2_STEREO_MODE, formatContext->stereoModeV2);
368                 if (formatContext->metadataSourceV2)    mm_attrs_set_string_by_name(attrs, MM_FILE_TAG_SPHERICAL_V2_METADATA_SOURCE, formatContext->metadataSourceV2);
369                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_SPHERICAL_V2_PROJ_TYPE, formatContext->projTypeV2);
370                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_SPHERICAL_V2_POSE_YAW, formatContext->poseYawV2);
371                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_SPHERICAL_V2_POSE_PITCH, formatContext->posePitchV2);
372                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_SPHERICAL_V2_POSE_ROLL, formatContext->poseRollV2);
373                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_SPHERICAL_V2_CBMP_LAYOUT, formatContext->cbmpLayoutV2);
374                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_SPHERICAL_V2_CBMP_PADDING, formatContext->cbmpPaddingV2);
375                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_SPHERICAL_V2_EQUI_BOUNDS_TOP, formatContext->equiBoundsTopV2);
376                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_SPHERICAL_V2_EQUI_BOUNDS_BOTTOM, formatContext->equiBoundsBottomV2);
377                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_SPHERICAL_V2_EQUI_BOUNDS_LEFT, formatContext->equiBoundsLeftV2);
378                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_SPHERICAL_V2_EQUI_BOUNDS_RIGHT, formatContext->equiBoundsRightV2);
379
380                 if ((formatContext->syncLyricsNum > 0) && (formatContext->syncLyrics))
381                         mm_attrs_set_data_by_name(attrs, MM_FILE_TAG_SYNCLYRICS, formatContext->syncLyrics, formatContext->syncLyricsNum);
382
383                 if (formatContext->unsyncLyrics)                mm_attrs_set_string_by_name(attrs, MM_FILE_TAG_UNSYNCLYRICS, formatContext->unsyncLyrics);
384
385                 if (formatContext->artwork && formatContext->artworkSize > 0) {
386                         void *artworkCopy = NULL;
387                         artworkCopy = mmfile_malloc((formatContext->artworkSize));
388                         if (NULL != artworkCopy) {
389                                 memcpy(artworkCopy, formatContext->artwork, formatContext->artworkSize);
390                                 mm_attrs_set_data_by_name(attrs, MM_FILE_TAG_ARTWORK, artworkCopy, formatContext->artworkSize);
391                                 mm_attrs_set_int_by_name(attrs, MM_FILE_TAG_ARTWORK_SIZE, formatContext->artworkSize);
392                                 if (formatContext->artworkMime) mm_attrs_set_string_by_name(attrs, MM_FILE_TAG_ARTWORK_MIME, formatContext->artworkMime);
393                         }
394                 }
395         } else if (formatContext->commandType == MM_FILE_CONTENTS) {
396                 /*get duration*/
397                 mm_attrs_set_int_by_name(attrs, MM_FILE_CONTENT_DURATION, formatContext->duration);
398                 mm_attrs_set_int_by_name(attrs, MM_FILE_CONTENT_AUDIO_TRACK_COUNT, formatContext->audioTotalTrackNum);
399                 mm_attrs_set_int_by_name(attrs, MM_FILE_CONTENT_VIDEO_TRACK_COUNT, formatContext->videoTotalTrackNum);
400
401                 if (formatContext->videoTotalTrackNum > 0 &&
402                     formatContext->nbStreams > 0 &&
403                     formatContext->streams[MMFILE_VIDEO_STREAM]) {
404
405                         MMFileFormatStream *videoStream = formatContext->streams[MMFILE_VIDEO_STREAM];
406
407                         mm_attrs_set_int_by_name(attrs, MM_FILE_CONTENT_VIDEO_FORMAT, formatContext->formatType);
408                         mm_attrs_set_int_by_name(attrs, MM_FILE_CONTENT_VIDEO_CODEC, videoStream->codecId);
409                         mm_attrs_set_int_by_name(attrs, MM_FILE_CONTENT_VIDEO_BITRATE, videoStream->bitRate);
410                         mm_attrs_set_int_by_name(attrs, MM_FILE_CONTENT_VIDEO_FPS, videoStream->framePerSec);
411                         mm_attrs_set_int_by_name(attrs, MM_FILE_CONTENT_VIDEO_WIDTH, videoStream->width);
412                         mm_attrs_set_int_by_name(attrs, MM_FILE_CONTENT_VIDEO_HEIGHT, videoStream->height);
413
414                         if (formatContext->thumbNail && formatContext->thumbNail->frameData) {
415                                 void *thumbNailCopy = NULL;
416                                 thumbNailCopy = mmfile_malloc(formatContext->thumbNail->frameSize);
417
418                                 if (NULL != thumbNailCopy) {
419                                         memcpy(thumbNailCopy, formatContext->thumbNail->frameData, formatContext->thumbNail->frameSize);
420                                         mm_attrs_set_data_by_name(attrs, MM_FILE_CONTENT_VIDEO_THUMBNAIL, thumbNailCopy, formatContext->thumbNail->frameSize);
421                                         mm_attrs_set_int_by_name(attrs, MM_FILE_CONTENT_VIDEO_WIDTH, formatContext->thumbNail->frameWidth);
422                                         mm_attrs_set_int_by_name(attrs, MM_FILE_CONTENT_VIDEO_HEIGHT, formatContext->thumbNail->frameHeight);
423                                 }
424                         }
425                 }
426
427                 if (formatContext->audioTotalTrackNum > 0 &&
428                     formatContext->nbStreams > 0 &&
429                     formatContext->streams[MMFILE_AUDIO_STREAM]) {
430
431                         MMFileFormatStream *audioStream = formatContext->streams[MMFILE_AUDIO_STREAM];
432
433                         mm_attrs_set_int_by_name(attrs, MM_FILE_CONTENT_AUDIO_CODEC, audioStream->codecId);
434                         mm_attrs_set_int_by_name(attrs, MM_FILE_CONTENT_AUDIO_CHANNELS, audioStream->nbChannel);
435                         mm_attrs_set_int_by_name(attrs, MM_FILE_CONTENT_AUDIO_BITRATE, audioStream->bitRate);
436                         mm_attrs_set_int_by_name(attrs, MM_FILE_CONTENT_AUDIO_SAMPLERATE, audioStream->samplePerSec);
437                         mm_attrs_set_int_by_name(attrs, MM_FILE_CONTENT_AUDIO_BITPERSAMPLE, audioStream->bitPerSample);
438                 }
439         } else {
440                 ret = -1;
441         }
442
443         /*commit attrs*/
444         mm_attrs_commit_all(attrs);
445
446         return ret;
447 }
448
449 static int
450 _get_contents_info(MMHandleType attrs, MMFileSourceType *src, MMFILE_PARSE_INFO *parse)
451 {
452         MMFileFormatContext *formatContext = NULL;
453         MMFileCodecContext  *codecContext = NULL;
454         MMFileFormatFrame    frameContext = {0, };
455         MMFileCodecFrame     codecFrame = {0, };
456         MMFileCodecFrame     decodedFrame = {0, };
457
458         int ret = 0;
459
460         if (!src || !parse)
461                 return FILEINFO_ERROR_FILE_INTERNAL;
462
463         ret = mmfile_format_open(&formatContext, src);
464         if (MMFILE_FORMAT_FAIL == ret || formatContext == NULL) {
465                 debug_error(DEBUG, "error: mmfile_format_open\n");
466                 ret = FILEINFO_ERROR_FILE_INTERNAL;
467                 goto exception;
468         }
469
470         if (parse->type >= MM_FILE_PARSE_TYPE_NORMAL) {
471                 if (parse->type == MM_FILE_PARSE_TYPE_SAFE)
472                         formatContext->cdis = 1;
473                 ret = mmfile_format_read_stream(formatContext);
474                 if (MMFILE_FORMAT_FAIL == ret) {
475                         debug_error(DEBUG, "error: mmfile_format_read_stream\n");
476                         ret = FILEINFO_ERROR_FILE_INTERNAL;
477                         goto exception;
478                 }
479
480                 parse->audio_track_num = formatContext->audioTotalTrackNum;
481                 parse->video_track_num = formatContext->videoTotalTrackNum;
482
483                 /* check uhqa content*/
484                 if (formatContext->streams[MMFILE_AUDIO_STREAM] != NULL) {
485                         parse->is_uhqa = formatContext->streams[MMFILE_AUDIO_STREAM]->is_uhqa;
486                 } else {
487                         parse->is_uhqa = FALSE;
488                 }
489
490                 if (parse->type >= MM_FILE_PARSE_TYPE_ALL) {
491                         if (formatContext->videoTotalTrackNum > 0) {
492
493 /*why below code needed?
494 This API is for extracting some attributes not metadata(TAG). mm_file_create_content_attrs() use this API.
495 but MMFileUtilGetMetaDataFromMP4() Extract just TAG info. That is needed for mm_file_create_tag_attrs()*/
496 #if 0
497                                 if (parse->type != MM_FILE_PARSE_TYPE_SAFE) {
498                                         if (formatContext->formatType == MM_FILE_FORMAT_3GP || formatContext->formatType == MM_FILE_FORMAT_MP4) {
499                                                 MMFileUtilGetMetaDataFromMP4(formatContext);
500                                         }
501                                 }
502 #endif
503                                 MMFileFormatStream *videoStream = formatContext->streams[MMFILE_VIDEO_STREAM];
504                                 unsigned int timestamp = _SEEK_POINT_;
505
506                                 ret = mmfile_format_read_frame(formatContext, timestamp, &frameContext);
507                                 if (MMFILE_FORMAT_FAIL == ret) {
508                                         debug_error(DEBUG, "error: mmfile_format_read_frame\n");
509                                         ret = FILEINFO_ERROR_FILE_INTERNAL;
510                                         goto warning;
511                                 }
512
513                                 if (frameContext.bCompressed) {
514                                         codecFrame.frameDataSize = frameContext.frameSize;
515                                         codecFrame.width = frameContext.frameWidth;
516                                         codecFrame.height = frameContext.frameHeight;
517                                         codecFrame.frameData = frameContext.frameData;
518                                         codecFrame.configLen = frameContext.configLenth;
519                                         codecFrame.configData = frameContext.configData;
520                                         codecFrame.version = videoStream->version;
521
522                                         ret = mmfile_codec_open(&codecContext, MMFILE_VIDEO_DECODE, videoStream->codecId, &codecFrame);
523                                         if (MMFILE_FORMAT_FAIL == ret) {
524                                                 debug_error(DEBUG, "error: mmfile_codec_open\n");
525                                                 ret = FILEINFO_ERROR_FILE_INTERNAL;
526                                                 goto warning;
527                                         }
528
529                                         ret = mmfile_codec_decode(codecContext, &decodedFrame);
530                                         if (MMFILE_FORMAT_FAIL == ret) {
531                                                 debug_error(DEBUG, "error: mmfile_codec_decode\n");
532                                                 ret = FILEINFO_ERROR_FILE_INTERNAL;
533                                                 goto warning;
534                                         }
535
536                                         /* set video thumbnail */
537                                         formatContext->thumbNail = mmfile_malloc(sizeof(MMFileFormatFrame));
538                                         if (NULL == formatContext->thumbNail) {
539                                                 debug_error(DEBUG, "error: mmfile_malloc\n");
540                                                 ret = FILEINFO_ERROR_FILE_INTERNAL;
541                                                 goto warning;
542                                         }
543
544                                         formatContext->thumbNail->frameSize = decodedFrame.frameDataSize;
545                                         formatContext->thumbNail->frameWidth = decodedFrame.width;
546                                         formatContext->thumbNail->frameHeight = decodedFrame.height;
547                                         formatContext->thumbNail->frameData = decodedFrame.frameData;
548                                         formatContext->thumbNail->configLenth = 0;
549                                         formatContext->thumbNail->configData = NULL;
550                                 } else {
551                                         formatContext->thumbNail = mmfile_malloc(sizeof(MMFileFormatFrame));
552                                         if (NULL == formatContext->thumbNail) {
553                                                 debug_error(DEBUG, "error: mmfile_format_read_frame\n");
554                                                 ret = FILEINFO_ERROR_FILE_INTERNAL;
555                                                 goto warning;
556                                         }
557
558                                         formatContext->thumbNail->frameSize = frameContext.frameSize;
559                                         formatContext->thumbNail->frameWidth = frameContext.frameWidth;
560                                         formatContext->thumbNail->frameHeight = frameContext.frameHeight;
561                                         formatContext->thumbNail->frameData = frameContext.frameData;
562                                         formatContext->thumbNail->configLenth = 0;
563                                         formatContext->thumbNail->configData = NULL;
564                                 }
565                         }
566                 }
567         } else {
568                 /**
569                  * if MM_FILE_PARSE_TYPE_SIMPLE, just get number of each stream.
570                  */
571                 parse->audio_track_num = formatContext->audioTotalTrackNum;
572                 parse->video_track_num = formatContext->videoTotalTrackNum;
573         }
574
575 #ifdef __MMFILE_TEST_MODE__
576         mmfile_format_print_frame(&frameContext);
577 #endif
578
579         formatContext->commandType = MM_FILE_CONTENTS;
580
581         if (parse->type >= MM_FILE_PARSE_TYPE_NORMAL)
582                 _info_set_attr_media(attrs, formatContext);
583
584         if (frameContext.bCompressed) {
585                 mmfile_free(frameContext.frameData);
586                 mmfile_free(frameContext.configData);
587
588                 if (decodedFrame.frameData) {
589                         mmfile_free(decodedFrame.frameData);
590                         formatContext->thumbNail->frameData = NULL;
591                 }
592                 if (decodedFrame.configData) {
593                         mmfile_free(decodedFrame.configData);
594                         formatContext->thumbNail->configData = NULL;
595                 }
596         } else {
597                 if (frameContext.frameData) {
598                         mmfile_free(frameContext.frameData);
599                         formatContext->thumbNail->frameData = NULL;
600                 }
601                 if (frameContext.configData) {
602                         mmfile_free(frameContext.configData);
603                         formatContext->thumbNail->configData = NULL;
604                 }
605         }
606
607         if (formatContext)  {
608                 mmfile_format_close(formatContext);
609         }
610         if (codecContext)   {
611                 mmfile_codec_close(codecContext);
612         }
613
614         return FILEINFO_ERROR_NONE;
615
616 warning:
617         formatContext->commandType = MM_FILE_CONTENTS;
618
619         if (frameContext.bCompressed) {
620                 mmfile_free(frameContext.frameData);
621                 mmfile_free(frameContext.configData);
622
623                 if (decodedFrame.frameData) {
624                         mmfile_free(decodedFrame.frameData);
625                         if (formatContext->thumbNail)
626                                 formatContext->thumbNail->frameData = NULL;
627                 }
628
629                 if (decodedFrame.configData) {
630                         mmfile_free(decodedFrame.configData);
631                         if (formatContext->thumbNail)
632                                 formatContext->thumbNail->configData = NULL;
633                 }
634         } else {
635                 if (frameContext.frameData) {
636                         mmfile_free(frameContext.frameData);
637                         if (formatContext->thumbNail)
638                                 formatContext->thumbNail->frameData = NULL;
639                 }
640
641                 if (frameContext.configData) {
642                         mmfile_free(frameContext.configData);
643                         if (formatContext->thumbNail)
644                                 formatContext->thumbNail->configData = NULL;
645                 }
646         }
647
648         if (parse->type >= MM_FILE_PARSE_TYPE_NORMAL)
649                 _info_set_attr_media(attrs, formatContext);
650
651         if (formatContext)  {
652                 mmfile_format_close(formatContext);
653         }
654         if (codecContext)   {
655                 mmfile_codec_close(codecContext);
656         }
657         return FILEINFO_ERROR_NONE;
658
659
660 exception:
661         if (frameContext.bCompressed) {
662                         mmfile_free(frameContext.frameData);
663                         mmfile_free(frameContext.configData);
664
665                 if (decodedFrame.frameData) {
666                         mmfile_free(decodedFrame.frameData);
667                         if (formatContext->thumbNail)
668                                 formatContext->thumbNail->frameData = NULL;
669                 }
670
671                 if (decodedFrame.configData) {
672                         mmfile_free(decodedFrame.configData);
673                         if (formatContext->thumbNail)
674                                 formatContext->thumbNail->configData = NULL;
675                 }
676         } else {
677                 if (frameContext.frameData) {
678                         mmfile_free(frameContext.frameData);
679                         if (formatContext->thumbNail)
680                                 formatContext->thumbNail->frameData = NULL;
681                 }
682
683                 if (frameContext.configData) {
684                         mmfile_free(frameContext.configData);
685                         if (formatContext->thumbNail)
686                                 formatContext->thumbNail->configData = NULL;
687                 }
688         }
689
690         if (formatContext)  {
691                 mmfile_format_close(formatContext);
692         }
693         /* if (codecContext)   { mmfile_codec_close(codecContext); } */ /*dead code*/
694
695         return ret;
696 }
697
698
699 static int
700 _get_tag_info(MMHandleType attrs, MMFileSourceType *src)
701 {
702         MMFileFormatContext *formatContext = NULL;
703         int ret = 0;
704
705         ret = mmfile_format_open(&formatContext, src);
706         if (MMFILE_FORMAT_FAIL == ret || formatContext == NULL) {
707                 debug_error(DEBUG, "error: mmfile_format_open\n");
708                 ret = FILEINFO_ERROR_FILE_INTERNAL;
709                 goto exception;
710         }
711
712         ret = mmfile_format_read_tag(formatContext);
713         if (MMFILE_FORMAT_FAIL == ret) {
714                 debug_warning(DEBUG, "reading tag is fail\n");
715                 ret = FILEINFO_ERROR_FILE_INTERNAL;
716                 goto exception;
717         }
718
719         formatContext->commandType = MM_FILE_TAG;
720
721         _info_set_attr_media(attrs, formatContext);
722
723         if (formatContext)  {
724                 mmfile_format_close(formatContext);
725         }
726
727         return FILEINFO_ERROR_NONE;
728
729
730 exception:
731         if (formatContext)  {
732                 mmfile_format_close(formatContext);
733         }
734
735         return FILEINFO_ERROR_FILE_INTERNAL;
736 }
737
738
739 /**
740  * global functions.
741  */
742 int mm_file_get_attrs(MMHandleType attrs, char **err_attr_name, const char *first_attribute_name, ...)
743 {
744         int ret = FILEINFO_ERROR_NONE;
745         va_list var_args;
746
747         if (!attrs) {
748                 debug_error(DEBUG, "Invalid arguments [attrs 0]\n");
749                 return FILEINFO_ERROR_INVALID_ARGUMENT;
750         }
751
752         if (first_attribute_name == NULL) {
753                 debug_error(DEBUG, "Invalid arguments [first_attribute_name null]\n");
754                 return FILEINFO_ERROR_INVALID_ARGUMENT;
755         }
756
757         /* get requested attributes */
758         va_start(var_args, first_attribute_name);
759         ret = mm_attrs_get_valist(attrs, err_attr_name, first_attribute_name, var_args);
760         va_end(var_args);
761
762         if (ret != FILEINFO_ERROR_NONE) {
763                 if (err_attr_name) {
764                         debug_error(DEBUG, "failed to get %s\n", *err_attr_name);
765                 }
766         }
767
768         return ret;
769 }
770
771 int mm_file_get_synclyrics_info(MMHandleType tag_attrs, int index, unsigned long *time_info, char **lyrics)
772 {
773         int ret = FILEINFO_ERROR_NONE;
774         AvSynclyricsInfo *sync_lyric_item = NULL;
775         GList *synclyrics_list = NULL;
776
777         debug_fenter(RELEASE);
778
779         if (tag_attrs == NULL) {
780                 debug_error(DEBUG, "invalid handle");
781                 return FILEINFO_ERROR_INVALID_ARGUMENT;
782         }
783
784         ret = mm_attrs_get_data_by_name(tag_attrs, MM_FILE_TAG_SYNCLYRICS, (void **)&synclyrics_list);
785         if (ret != FILEINFO_ERROR_NONE) {
786                 debug_warning(RELEASE, "get data fail");
787                 return ret;
788         }
789
790         if (synclyrics_list != NULL) {
791
792                 sync_lyric_item = (AvSynclyricsInfo *)g_list_nth_data(synclyrics_list, index);
793
794                 if (sync_lyric_item == NULL) {
795                         debug_warning(RELEASE, "synclyric item is NULL");
796                         return FILEINFO_ERROR_ATTR_NOT_EXIST;
797                 }
798
799                 *time_info = sync_lyric_item->time_info;
800                 *lyrics = sync_lyric_item->lyric_info;
801
802         } else {
803                 debug_warning(RELEASE, "synclyrics_list is NULL");
804                 return FILEINFO_ERROR_ATTR_NOT_EXIST;
805         }
806
807         return ret;
808
809 }
810
811 int mm_file_create_tag_attrs(MMHandleType *tag_attrs, const char *filename)
812 {
813         int ret = FILEINFO_ERROR_NONE;
814         MMHandleType attrs = NULL;
815         MMFileSourceType src;
816
817         debug_fenter(RELEASE);
818
819         /* Check argument here */
820         if (tag_attrs == NULL) {
821                 debug_error(DEBUG, "Invalid arguments [tag null]\n");
822                 return FILEINFO_ERROR_INVALID_ARGUMENT;
823         }
824         if (filename == NULL) {
825                 debug_error(DEBUG, "Invalid arguments [filename null]\n");
826                 return FILEINFO_ERROR_INVALID_ARGUMENT;
827         }
828         if (strlen(filename) == 0)      {
829                 debug_error(DEBUG, "Invalid arguments [filename size 0]\n");
830                 return FILEINFO_ERROR_INVALID_ARGUMENT;
831         }
832
833
834 #ifdef __MMFILE_DYN_LOADING__
835         MMFILE_FUNC_HANDLE func_handle;
836
837         ret = _load_dynamic_functions(&func_handle);
838         if (ret == 0) {
839                 debug_error(DEBUG, "load library error\n");
840                 return FILEINFO_ERROR_FILE_INTERNAL;
841         }
842 #endif
843
844         /*set source file infomation*/
845         MM_FILE_SET_MEDIA_FILE_SRC(src, filename);
846
847         ret = _is_file_exist(filename);
848         if (ret != FILEINFO_ERROR_NONE) {
849                 goto END;
850         }
851
852         /*set attrs*/
853         ret = mm_attrs_new(g_tag_attrs, ARRAY_SIZE(g_tag_attrs), "tag", NULL, NULL, &attrs);
854         if (ret) {
855                 debug_error(DEBUG, "attribute internal error.\n");
856                 ret = FILEINFO_ERROR_FILE_INTERNAL;
857                 goto END;
858         }
859
860         ret = _get_tag_info(attrs, &src);
861         if (ret != FILEINFO_ERROR_NONE) {
862                 mm_attrs_free(attrs);
863                 attrs = NULL;
864                 debug_error(DEBUG, "failed to get tag: %s\n", filename);
865         }
866
867         *tag_attrs = attrs;
868
869 END:
870 #ifdef __MMFILE_DYN_LOADING__
871         _unload_dynamic_functions(&func_handle);
872 #endif
873
874         debug_fleave(RELEASE);
875
876         return ret;
877 }
878
879
880 EXPORT_API
881 int mm_file_destroy_tag_attrs(MMHandleType tag_attrs)
882 {
883         void *artwork = NULL;
884         GList *synclyrics_list = NULL;
885         int ret = FILEINFO_ERROR_NONE;
886
887         debug_fenter(RELEASE);
888
889         if (tag_attrs == NULL) {
890                 debug_error(DEBUG, "invalid handle.\n");
891                 return FILEINFO_ERROR_INVALID_ARGUMENT;
892         }
893
894         ret = mm_attrs_get_data_by_name(tag_attrs, MM_FILE_TAG_ARTWORK, &artwork);
895         mmfile_free(artwork);
896
897         ret = mm_attrs_get_data_by_name(tag_attrs, MM_FILE_TAG_SYNCLYRICS, (void **)&synclyrics_list);
898         mm_file_free_synclyrics_list(synclyrics_list);
899         mm_attrs_free(tag_attrs);
900
901         debug_fleave(RELEASE);
902
903         return ret;
904 }
905
906 EXPORT_API
907 int mm_file_create_content_attrs(MMHandleType *contents_attrs, const char *filename)
908 {
909         MMHandleType attrs = NULL;
910         MMFileSourceType src = {0, };
911         MMFILE_PARSE_INFO parse = {0, };
912         int ret = 0;
913
914         debug_fenter(RELEASE);
915
916         /* Check argument here */
917         if (contents_attrs == NULL) {
918                 debug_error(DEBUG, "Invalid arguments [contents null]\n");
919                 return FILEINFO_ERROR_INVALID_ARGUMENT;
920         }
921         if (filename == NULL) {
922                 debug_error(DEBUG, "Invalid arguments [filename null]\n");
923                 return FILEINFO_ERROR_INVALID_ARGUMENT;
924         }
925         if (strlen(filename) == 0)      {
926                 debug_error(DEBUG, "Invalid arguments [filename size 0]\n");
927                 return FILEINFO_ERROR_INVALID_ARGUMENT;
928         }
929
930
931 #ifdef __MMFILE_DYN_LOADING__
932         MMFILE_FUNC_HANDLE func_handle;
933
934 #ifdef CHECK_TIME
935         int64_t ti;
936         ti = gettime();
937 #endif
938
939         ret = _load_dynamic_functions(&func_handle);
940         if (ret == 0) {
941                 debug_error(DEBUG, "load library error\n");
942                 return FILEINFO_ERROR_FILE_INTERNAL;
943         }
944
945 #ifdef CHECK_TIME
946         debug_msg(DEBUG, "_load_dynamic_functions() = %lld\n", gettime() - ti);
947 #endif
948
949 #endif
950
951         /*set source file infomation*/
952         MM_FILE_SET_MEDIA_FILE_SRC(src, filename);
953
954         ret = _is_file_exist(filename);
955         if (ret != FILEINFO_ERROR_NONE) {
956                 goto END;
957         }
958
959         /*set attrs*/
960         ret = mm_attrs_new(g_content_attrs, ARRAY_SIZE(g_content_attrs), "content", NULL, NULL, &attrs);
961         if (ret) {
962                 debug_error(DEBUG, "attribute internal error.\n");
963                 ret = FILEINFO_ERROR_FILE_INTERNAL;
964                 goto END;
965         }
966
967
968         parse.type = MM_FILE_PARSE_TYPE_ALL;
969         ret = _get_contents_info(attrs, &src, &parse);
970         if (ret != FILEINFO_ERROR_NONE) {
971                 mm_attrs_free(attrs);
972                 attrs = NULL;
973                 debug_error(DEBUG, "failed to get contents: %s\n", filename);
974         }
975
976         *contents_attrs = attrs;
977
978
979 END:
980 #ifdef __MMFILE_DYN_LOADING__
981
982 #ifdef CHECK_TIME
983         ti = gettime();
984 #endif
985
986         _unload_dynamic_functions(&func_handle);
987
988 #ifdef CHECK_TIME
989         debug_msg(DEBUG, "_unload_dynamic_functions() = %lld\n", gettime() - ti);
990 #endif
991
992 #endif
993
994         debug_fleave(RELEASE);
995
996         return ret;
997 }
998
999
1000 EXPORT_API
1001 int mm_file_create_tag_attrs_from_memory(MMHandleType *tag_attrs, const void *data, unsigned int size, int format)
1002 {
1003         MMHandleType attrs = NULL;
1004         MMFileSourceType src;
1005         /*MMFILE_PARSE_INFO parse = {0, };*/
1006         int ret = 0;
1007
1008         debug_fenter(RELEASE);
1009
1010         /* Check argument here */
1011         if (tag_attrs == NULL || data == NULL) {
1012                 debug_error(DEBUG, "Invalid arguments\n");
1013                 return FILEINFO_ERROR_INVALID_ARGUMENT;
1014         }
1015
1016 #ifdef __MMFILE_DYN_LOADING__
1017         MMFILE_FUNC_HANDLE func_handle;
1018
1019         ret = _load_dynamic_functions(&func_handle);
1020         if (ret == 0) {
1021                 debug_error(DEBUG, "load library error\n");
1022                 return FILEINFO_ERROR_FILE_INTERNAL;
1023         }
1024 #endif
1025
1026         MM_FILE_SET_MEDIA_MEM_SRC(src, data, size, format);
1027
1028         /*set attrs*/
1029         ret = mm_attrs_new(g_tag_attrs, ARRAY_SIZE(g_tag_attrs), "tag", NULL, NULL, &attrs);
1030         if (ret) {
1031                 debug_error(DEBUG, "attribute internal error.\n");
1032                 ret = FILEINFO_ERROR_FILE_INTERNAL;
1033                 goto END;
1034         }
1035
1036         /*parse.type = MM_FILE_PARSE_TYPE_ALL;*/
1037         ret = _get_tag_info(attrs, &src);
1038         if (ret != FILEINFO_ERROR_NONE) {
1039                 mm_attrs_free(attrs);
1040                 attrs = NULL;
1041                 debug_error(DEBUG, "failed to get tag");
1042         }
1043
1044         *tag_attrs = attrs;
1045
1046 END:
1047 #ifdef __MMFILE_DYN_LOADING__
1048         _unload_dynamic_functions(&func_handle);
1049 #endif
1050
1051         debug_fleave(RELEASE);
1052
1053         return ret;
1054 }
1055
1056
1057 EXPORT_API
1058 int mm_file_create_content_attrs_from_memory(MMHandleType *contents_attrs, const void *data, unsigned int size, int format)
1059 {
1060         MMHandleType attrs = NULL;
1061         MMFileSourceType src;
1062         MMFILE_PARSE_INFO parse = {0, };
1063         int ret = 0;
1064
1065         debug_fenter(RELEASE);
1066
1067         /* Check argument here */
1068         if (contents_attrs == NULL || data == NULL) {
1069                 debug_error(DEBUG, "Invalid arguments\n");
1070                 return FILEINFO_ERROR_INVALID_ARGUMENT;
1071         }
1072
1073 #ifdef __MMFILE_DYN_LOADING__
1074         MMFILE_FUNC_HANDLE func_handle;
1075
1076         ret = _load_dynamic_functions(&func_handle);
1077         if (ret == 0) {
1078                 debug_error(DEBUG, "load library error\n");
1079                 return FILEINFO_ERROR_FILE_INTERNAL;
1080         }
1081 #endif
1082
1083         MM_FILE_SET_MEDIA_MEM_SRC(src, data, size, format);
1084
1085         /*set attrs*/
1086         ret = mm_attrs_new(g_content_attrs, ARRAY_SIZE(g_content_attrs), "content", NULL, NULL, &attrs);
1087         if (ret) {
1088                 debug_error(DEBUG, "attribute internal error.\n");
1089                 ret = FILEINFO_ERROR_FILE_INTERNAL;
1090                 goto END;
1091         }
1092
1093         parse.type = MM_FILE_PARSE_TYPE_ALL;
1094         ret = _get_contents_info(attrs, &src, &parse);
1095         if (ret != FILEINFO_ERROR_NONE) {
1096                 mm_attrs_free(attrs);
1097                 attrs = NULL;
1098                 debug_error(DEBUG, "failed to get contents");
1099         }
1100
1101         *contents_attrs = attrs;
1102
1103 END:
1104 #ifdef __MMFILE_DYN_LOADING__
1105         _unload_dynamic_functions(&func_handle);
1106 #endif
1107
1108         debug_fleave(RELEASE);
1109
1110         return ret;
1111 }
1112
1113
1114 EXPORT_API
1115 int mm_file_destroy_content_attrs(MMHandleType contents_attrs)
1116 {
1117         void *thumbnail = NULL;
1118         int ret = FILEINFO_ERROR_NONE;
1119
1120         debug_fenter(RELEASE);
1121
1122         if (contents_attrs == NULL) {
1123                 debug_error(DEBUG, "invalid handle.\n");
1124                 return FILEINFO_ERROR_INVALID_ARGUMENT;
1125         }
1126
1127         ret = mm_attrs_get_data_by_name(contents_attrs, MM_FILE_CONTENT_VIDEO_THUMBNAIL, &thumbnail);
1128         mmfile_free(thumbnail);
1129
1130         mm_attrs_free(contents_attrs);
1131
1132         debug_fleave(RELEASE);
1133
1134         return ret;
1135 }
1136
1137
1138 EXPORT_API
1139 int mm_file_get_stream_info(const char *filename, int *audio_stream_num, int *video_stream_num)
1140 {
1141         MMFileSourceType     src = {0, };
1142         MMFILE_PARSE_INFO    parse = {0, };
1143
1144         int ret = 0;
1145
1146         debug_fenter(RELEASE);
1147
1148         if (filename == NULL || strlen(filename) == 0 || audio_stream_num == NULL || video_stream_num == NULL) {
1149                 debug_error(DEBUG, "Invalid arguments\n");
1150                 return FILEINFO_ERROR_INVALID_ARGUMENT;
1151         }
1152
1153 #ifdef __MMFILE_DYN_LOADING__
1154         MMFILE_FUNC_HANDLE func_handle;
1155
1156         ret = _load_dynamic_functions(&func_handle);
1157         if (ret == 0) {
1158                 debug_error(DEBUG, "load library error\n");
1159                 return FILEINFO_ERROR_FILE_INTERNAL;
1160         }
1161 #endif
1162
1163         /*set source file infomation*/
1164         MM_FILE_SET_MEDIA_FILE_SRC(src, filename);
1165
1166         ret = _is_file_exist(filename);
1167         if (ret != FILEINFO_ERROR_NONE) {
1168                 goto END;
1169         }
1170
1171         parse.type = MM_FILE_PARSE_TYPE_SIMPLE;
1172         ret = _get_contents_info(NULL, &src, &parse);
1173         if (ret != FILEINFO_ERROR_NONE) {
1174                 debug_error(DEBUG, "failed to get stream info: %s\n", filename);
1175         } else {
1176                 if (parse.audio_track_num == 0 && parse.video_track_num == 0) {
1177                         debug_error(DEBUG, "empty header. retry to get stream info: %s\n", filename);
1178                         parse.type = MM_FILE_PARSE_TYPE_NORMAL;
1179                         ret = _get_contents_info(NULL, &src, &parse);
1180                 }
1181         }
1182
1183         /*set number of each stream*/
1184         *audio_stream_num = parse.audio_track_num;
1185         *video_stream_num = parse.video_track_num;
1186
1187 END:
1188 #ifdef __MMFILE_DYN_LOADING__
1189         _unload_dynamic_functions(&func_handle);
1190 #endif
1191
1192         debug_fleave(RELEASE);
1193
1194         return ret;
1195 }
1196
1197 EXPORT_API
1198 int mm_file_create_content_attrs_simple(MMHandleType *contents_attrs, const char *filename)
1199 {
1200         MMHandleType attrs = NULL;
1201         MMFileSourceType src = {0, };
1202         MMFILE_PARSE_INFO parse = {0, };
1203         int ret = 0;
1204
1205         debug_fenter(RELEASE);
1206
1207 #ifdef __MMFILE_DYN_LOADING__
1208         MMFILE_FUNC_HANDLE func_handle;
1209
1210         ret = _load_dynamic_functions(&func_handle);
1211         if (ret == 0) {
1212                 debug_error(DEBUG, "load library error\n");
1213                 return FILEINFO_ERROR_FILE_INTERNAL;
1214         }
1215 #endif
1216         if (filename == NULL) {
1217                 ret =  FILEINFO_ERROR_INVALID_ARGUMENT;
1218                 goto END;
1219         } else {
1220                 if (strlen(filename) == 0) {
1221                         ret =  FILEINFO_ERROR_INVALID_ARGUMENT;
1222                         goto END;
1223                 }
1224         }
1225
1226         /*set source file infomation*/
1227         MM_FILE_SET_MEDIA_FILE_SRC(src, filename);
1228
1229         ret = _is_file_exist(filename);
1230         if (ret != FILEINFO_ERROR_NONE) {
1231                 goto END;
1232         }
1233
1234         /*set attrs*/
1235         ret = mm_attrs_new(g_content_attrs, ARRAY_SIZE(g_content_attrs), "content", NULL, NULL, &attrs);
1236         if (ret) {
1237                 debug_error(DEBUG, "attribute internal error.\n");
1238                 ret = FILEINFO_ERROR_FILE_INTERNAL;
1239                 goto END;
1240         }
1241
1242         parse.type = MM_FILE_PARSE_TYPE_NORMAL;
1243         ret = _get_contents_info(attrs, &src, &parse);
1244         if (ret != FILEINFO_ERROR_NONE) {
1245                 mm_attrs_free(attrs);
1246                 attrs = NULL;
1247                 debug_error(DEBUG, "failed to get contents: %s\n", filename);
1248         }
1249
1250         *contents_attrs = attrs;
1251
1252 END:
1253 #ifdef __MMFILE_DYN_LOADING__
1254         _unload_dynamic_functions(&func_handle);
1255 #endif
1256
1257         debug_fleave(RELEASE);
1258
1259         return ret;
1260 }
1261
1262 EXPORT_API
1263 int mm_file_create_content_attrs_safe(MMHandleType *contents_attrs, const char *filename)
1264 {
1265         MMHandleType attrs = NULL;
1266         MMFileSourceType src = {0, };
1267         MMFILE_PARSE_INFO parse = {0, };
1268         int ret = 0;
1269
1270         debug_fenter(RELEASE);
1271
1272 #ifdef __MMFILE_DYN_LOADING__
1273         MMFILE_FUNC_HANDLE func_handle;
1274
1275         ret = _load_dynamic_functions(&func_handle);
1276         if (ret == 0) {
1277                 debug_error(DEBUG, "load library error\n");
1278                 return FILEINFO_ERROR_FILE_INTERNAL;
1279         }
1280 #endif
1281         if (filename == NULL) {
1282                 ret = FILEINFO_ERROR_INVALID_ARGUMENT;
1283                 goto END;
1284         } else {
1285                 if (strlen(filename) == 0) {
1286                         ret = FILEINFO_ERROR_INVALID_ARGUMENT;
1287                         goto END;
1288                 }
1289         }
1290
1291         /*set source file infomation*/
1292         MM_FILE_SET_MEDIA_FILE_SRC(src, filename);
1293
1294         ret = _is_file_exist(filename);
1295         if (ret != FILEINFO_ERROR_NONE) {
1296                 goto END;
1297         }
1298
1299         /*set attrs*/
1300         ret = mm_attrs_new(g_content_attrs, ARRAY_SIZE(g_content_attrs), "content", NULL, NULL, &attrs);
1301         if (ret) {
1302                 debug_error(DEBUG, "attribute internal error.\n");
1303                 ret = FILEINFO_ERROR_FILE_INTERNAL;
1304                 goto END;
1305         }
1306
1307         parse.type = MM_FILE_PARSE_TYPE_SAFE;
1308         ret = _get_contents_info(attrs, &src, &parse);
1309         if (ret != FILEINFO_ERROR_NONE) {
1310                 mm_attrs_free(attrs);
1311                 attrs = NULL;
1312                 debug_error(DEBUG, "failed to get contents: %s\n", filename);
1313         }
1314
1315         *contents_attrs = attrs;
1316
1317 END:
1318 #ifdef __MMFILE_DYN_LOADING__
1319         _unload_dynamic_functions(&func_handle);
1320 #endif
1321
1322         debug_fleave(RELEASE);
1323
1324         return ret;
1325 }
1326
1327 EXPORT_API
1328 int mm_file_get_video_frame(const char *path, double timestamp, bool is_accurate, unsigned char **frame, int *size, int *width, int *height)
1329 {
1330         int ret = 0;
1331         void *formatFuncHandle = NULL;
1332
1333         if (path == NULL) {
1334                 debug_error(DEBUG, "Invalid arguments [Path is Null]\n");
1335                 return FILEINFO_ERROR_INVALID_ARGUMENT;
1336         }
1337
1338 #ifdef __MMFILE_DYN_LOADING__
1339         /* Get from function argument */
1340         formatFuncHandle = dlopen(MMFILE_FORMAT_SO_FILE_NAME, RTLD_LAZY);
1341         if (!formatFuncHandle) {
1342                 debug_error(DEBUG, "error : dlopen");
1343                 goto exception;
1344         }
1345
1346         mmfile_format_get_frame = dlsym(formatFuncHandle, "mmfile_format_get_frame");
1347         if (!mmfile_format_get_frame) {
1348                 debug_error(DEBUG, "error : load library");
1349                 goto exception;
1350         }
1351 #endif
1352
1353         debug_msg(RELEASE, "file path [%s] is_accurate [%d]", path, is_accurate);
1354
1355         ret = mmfile_format_get_frame(path, timestamp, is_accurate, frame, size, width, height);
1356         if (ret  == MMFILE_FORMAT_FAIL) {
1357                 debug_error(DEBUG, "error : get frame");
1358                 goto exception;
1359         }
1360
1361         if (formatFuncHandle) dlclose(formatFuncHandle);
1362
1363         return FILEINFO_ERROR_NONE;
1364
1365 exception:
1366         if (formatFuncHandle) dlclose(formatFuncHandle);
1367
1368         return FILEINFO_ERROR_FILE_INTERNAL;
1369 }
1370
1371 EXPORT_API
1372 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)
1373 {
1374         int ret = 0;
1375         void *formatFuncHandle = NULL;
1376
1377         if (data == NULL) {
1378                 debug_error(DEBUG, "Invalid arguments [data is Null]\n");
1379                 return FILEINFO_ERROR_INVALID_ARGUMENT;
1380         }
1381
1382         if (datasize == 0) {
1383                 debug_error(DEBUG, "Invalid arguments [datasize is zero]\n");
1384                 return FILEINFO_ERROR_INVALID_ARGUMENT;
1385         }
1386
1387 #ifdef __MMFILE_DYN_LOADING__
1388         /* Get from function argument */
1389         formatFuncHandle = dlopen(MMFILE_FORMAT_SO_FILE_NAME, RTLD_LAZY);
1390         if (!formatFuncHandle) {
1391                 debug_error(DEBUG, "error : dlopen");
1392                 goto exception;
1393         }
1394
1395         mmfile_format_get_frame_from_memory = dlsym(formatFuncHandle, "mmfile_format_get_frame_from_memory");
1396         if (!mmfile_format_get_frame_from_memory) {
1397                 debug_error(DEBUG, "error : load library");
1398                 goto exception;
1399         }
1400 #endif
1401
1402         debug_msg(RELEASE, "data [%p], data_size[%d], is_accurate [%d]", data, datasize, is_accurate);
1403
1404         ret = mmfile_format_get_frame_from_memory(data, datasize, timestamp, is_accurate, frame, size, width, height);
1405         if (ret  == MMFILE_FORMAT_FAIL) {
1406                 debug_error(DEBUG, "error : get frame");
1407                 goto exception;
1408         }
1409
1410         if (formatFuncHandle) dlclose(formatFuncHandle);
1411
1412         return FILEINFO_ERROR_NONE;
1413
1414 exception:
1415         if (formatFuncHandle) dlclose(formatFuncHandle);
1416
1417         return FILEINFO_ERROR_FILE_INTERNAL;
1418 }
1419
1420 EXPORT_API
1421 int mm_file_check_uhqa(const char *filename, bool *is_uhqa)
1422 {
1423         MMHandleType attrs = NULL;
1424         MMFileSourceType src = {0, };
1425         MMFILE_PARSE_INFO parse = {0, };
1426         int ret = 0;
1427
1428 #ifdef __MMFILE_DYN_LOADING__
1429         MMFILE_FUNC_HANDLE func_handle;
1430
1431         ret = _load_dynamic_functions(&func_handle);
1432         if (ret == 0) {
1433                 debug_error(DEBUG, "load library error\n");
1434                 return FILEINFO_ERROR_FILE_INTERNAL;
1435         }
1436 #endif
1437         if (filename == NULL) {
1438                 ret = FILEINFO_ERROR_INVALID_ARGUMENT;
1439                 goto END;
1440         } else {
1441                 if (strlen(filename) == 0) {
1442                         ret = FILEINFO_ERROR_INVALID_ARGUMENT;
1443                         goto END;
1444                 }
1445         }
1446
1447         /*set source file infomation*/
1448         MM_FILE_SET_MEDIA_FILE_SRC(src, filename);
1449
1450         ret = _is_file_exist(filename);
1451         if (ret != FILEINFO_ERROR_NONE) {
1452                 goto END;
1453         }
1454
1455         /*set attrs*/
1456         ret = mm_attrs_new(g_content_attrs, ARRAY_SIZE(g_content_attrs), "content", NULL, NULL, &attrs);
1457         if (ret) {
1458                 debug_error(DEBUG, "attribute internal error.\n");
1459                 ret = FILEINFO_ERROR_FILE_INTERNAL;
1460                 goto END;
1461         }
1462
1463         parse.type = MM_FILE_PARSE_TYPE_NORMAL;
1464         ret = _get_contents_info(attrs, &src, &parse);
1465         if (ret == FILEINFO_ERROR_NONE) {
1466                 *is_uhqa = parse.is_uhqa;
1467         } else {
1468                 debug_error(DEBUG, "_get_contents_info failed\n");
1469                 *is_uhqa = FALSE;
1470         }
1471
1472         mm_attrs_free(attrs);
1473         attrs = NULL;
1474
1475 END:
1476 #ifdef __MMFILE_DYN_LOADING__
1477         _unload_dynamic_functions(&func_handle);
1478 #endif
1479
1480         debug_fleave(RELEASE);
1481
1482         return ret;
1483 }