remove MMFileUtilGetMetaDataFromMP4() when extract content attributes. because MMFile...
[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
31 /* internal MM header files */
32 #include <mm_attrs_private.h>
33
34 /* internal MM File headers */
35 #include "mm_file_debug.h"
36 #include "mm_file_formats.h"
37 #include "mm_file_format_frame.h"
38 #include "mm_file_codecs.h"
39 #include "mm_file_utils.h"
40
41
42 #include <sys/time.h>
43
44 /*#define CHECK_TIME */
45
46 #ifdef CHECK_TIME
47 int64_t gettime(void)
48 {
49         struct timeval tv;
50         gettimeofday(&tv, NULL);
51         return (int64_t)tv.tv_sec * 1000000 + tv.tv_usec;
52 }
53 #endif
54
55
56 /**
57  * Defines.
58  */
59
60 #ifndef ARRAY_SIZE
61 #define ARRAY_SIZE(arr)         (sizeof(arr) / sizeof((arr)[0]))
62 #endif
63
64 #define _SEEK_POINT_    3000            /*1000 = 1 seconds*/
65
66 #define MM_FILE_TAG_SYNCLYRICS  "tag-synclyrics"        /**< Synchronized Lyrics Information*/
67
68
69 enum {
70         MM_FILE_TAG,
71         MM_FILE_CONTENTS,
72         MM_FILE_INVALID,
73 };
74
75 enum {
76         MM_FILE_PARSE_TYPE_SIMPLE,              /*parse audio/video track num only*/
77         MM_FILE_PARSE_TYPE_NORMAL,              /*parse infomation without thumbnail*/
78         MM_FILE_PARSE_TYPE_ALL,                 /*parse all infomation*/
79         MM_FILE_PARSE_TYPE_SAFE,                /*parse infomation without both thumbnail and stream full-searching*/
80 };
81
82 typedef struct {
83         int     type;
84         int     audio_track_num;
85         int     video_track_num;
86         bool is_uhqa;
87 } MMFILE_PARSE_INFO;
88
89 typedef struct {
90         void *formatFuncHandle;
91         void *codecFuncHandle;
92 } MMFILE_FUNC_HANDLE;
93
94
95
96 /**
97  * global values.
98  */
99 static mmf_attrs_construct_info_t g_tag_attrs[] = {
100         {(char *)"tag-artist",                  MMF_VALUE_TYPE_STRING,  MM_ATTRS_FLAG_RW, (void *)NULL},
101         {(char *)"tag-title",                   MMF_VALUE_TYPE_STRING,  MM_ATTRS_FLAG_RW, (void *)NULL},
102         {(char *)"tag-album",                   MMF_VALUE_TYPE_STRING,  MM_ATTRS_FLAG_RW, (void *)NULL},
103         {(char *)"tag-album-artist",    MMF_VALUE_TYPE_STRING,  MM_ATTRS_FLAG_RW, (void *)NULL},
104         {(char *)"tag-genre",                   MMF_VALUE_TYPE_STRING,  MM_ATTRS_FLAG_RW, (void *)NULL},
105         {(char *)"tag-author",                  MMF_VALUE_TYPE_STRING,  MM_ATTRS_FLAG_RW, (void *)NULL},
106         {(char *)"tag-copyright",               MMF_VALUE_TYPE_STRING,  MM_ATTRS_FLAG_RW, (void *)NULL},
107         {(char *)"tag-date",                    MMF_VALUE_TYPE_STRING,  MM_ATTRS_FLAG_RW, (void *)NULL},
108         {(char *)"tag-description",             MMF_VALUE_TYPE_STRING,  MM_ATTRS_FLAG_RW, (void *)NULL},
109         {(char *)"tag-comment",         MMF_VALUE_TYPE_STRING,  MM_ATTRS_FLAG_RW, (void *)NULL},
110         {(char *)"tag-artwork",         MMF_VALUE_TYPE_DATA,    MM_ATTRS_FLAG_RW, (void *)NULL},
111         {(char *)"tag-artwork-size",    MMF_VALUE_TYPE_INT,             MM_ATTRS_FLAG_RW, (void *)0},
112         {(char *)"tag-artwork-mime",    MMF_VALUE_TYPE_STRING,  MM_ATTRS_FLAG_RW, (void *)NULL},
113         {(char *)"tag-track-num",               MMF_VALUE_TYPE_STRING,  MM_ATTRS_FLAG_RW, (void *)NULL},
114         {(char *)"tag-classification",  MMF_VALUE_TYPE_STRING,  MM_ATTRS_FLAG_RW, (void *)NULL},
115         {(char *)"tag-rating",                  MMF_VALUE_TYPE_STRING,  MM_ATTRS_FLAG_RW, (void *)NULL},
116         {(char *)"tag-longitude",               MM_ATTRS_TYPE_DOUBLE,   MM_ATTRS_FLAG_RW, (void *)0},
117         {(char *)"tag-latitude",                MM_ATTRS_TYPE_DOUBLE,   MM_ATTRS_FLAG_RW, (void *)0},
118         {(char *)"tag-altitude",                MM_ATTRS_TYPE_DOUBLE,   MM_ATTRS_FLAG_RW, (void *)0},
119         {(char *)"tag-conductor",               MMF_VALUE_TYPE_STRING,  MM_ATTRS_FLAG_RW, (void *)NULL},
120         {(char *)"tag-unsynclyrics",    MMF_VALUE_TYPE_STRING,  MM_ATTRS_FLAG_RW, (void *)NULL},
121         {(char *)"tag-synclyrics-num",  MMF_VALUE_TYPE_INT,             MM_ATTRS_FLAG_RW, (void *)0},
122         {(char *)"tag-synclyrics",              MMF_VALUE_TYPE_DATA,    MM_ATTRS_FLAG_RW, (void *)NULL},
123         {(char *)"tag-recdate",         MMF_VALUE_TYPE_STRING,  MM_ATTRS_FLAG_RW, (void *)NULL},
124         {(char *)"tag-rotate",                  MMF_VALUE_TYPE_STRING,  MM_ATTRS_FLAG_RW, (void *)NULL},
125         {(char *)"tag-cdis",                    MMF_VALUE_TYPE_INT,             MM_ATTRS_FLAG_RW, (void *)0},
126         {(char *)"tag-smta",                    MMF_VALUE_TYPE_INT,             MM_ATTRS_FLAG_RW, (void *)0},
127         {(char *)"tag-360",                     MMF_VALUE_TYPE_INT,             MM_ATTRS_FLAG_RW, (void *)0},
128         {(char *)"tag-stitched_info",   MMF_VALUE_TYPE_INT,             MM_ATTRS_FLAG_RW, (void *)0},
129 };
130
131 static mmf_attrs_construct_info_t g_content_attrs[] = {
132         {(char *)"content-duration",                    MMF_VALUE_TYPE_INT,             MM_ATTRS_FLAG_RW, (void *)0},
133         {(char *)"content-video-codec",         MMF_VALUE_TYPE_INT,             MM_ATTRS_FLAG_RW, (void *)0},
134         {(char *)"content-video-format",                MMF_VALUE_TYPE_INT,             MM_ATTRS_FLAG_RW, (void *)0},
135         {(char *)"content-video-bitrate",               MMF_VALUE_TYPE_INT,             MM_ATTRS_FLAG_RW, (void *)0},
136         {(char *)"content-video-fps",                   MMF_VALUE_TYPE_INT,             MM_ATTRS_FLAG_RW, (void *)0},
137         {(char *)"content-video-width",         MMF_VALUE_TYPE_INT,             MM_ATTRS_FLAG_RW, (void *)0},
138         {(char *)"content-video-height",                MMF_VALUE_TYPE_INT,             MM_ATTRS_FLAG_RW, (void *)0},
139         {(char *)"content-video-thumbnail",             MMF_VALUE_TYPE_DATA,    MM_ATTRS_FLAG_RW, (void *)NULL},
140         {(char *)"content-video-track-index",   MMF_VALUE_TYPE_INT,             MM_ATTRS_FLAG_RW, (void *)0},
141         {(char *)"content-video-track-count",   MMF_VALUE_TYPE_INT,             MM_ATTRS_FLAG_RW, (void *)0},
142         {(char *)"content-audio-codec",         MMF_VALUE_TYPE_INT,             MM_ATTRS_FLAG_RW, (void *)0},
143         {(char *)"content-audio-bitrate",               MMF_VALUE_TYPE_INT,             MM_ATTRS_FLAG_RW, (void *)0},
144         {(char *)"content-audio-channels",              MMF_VALUE_TYPE_INT,             MM_ATTRS_FLAG_RW, (void *)0},
145         {(char *)"content-audio-samplerate",    MMF_VALUE_TYPE_INT,             MM_ATTRS_FLAG_RW, (void *)0},
146         {(char *)"content-audio-track-index",   MMF_VALUE_TYPE_INT,             MM_ATTRS_FLAG_RW, (void *)0},
147         {(char *)"content-audio-track-count",   MMF_VALUE_TYPE_INT,             MM_ATTRS_FLAG_RW, (void *)0},
148         {(char *)"content-audio-bitpersample",  MMF_VALUE_TYPE_INT,             MM_ATTRS_FLAG_RW, (void *)0},
149 };
150
151 #ifdef __MMFILE_DYN_LOADING__
152 #define MMFILE_FORMAT_SO_FILE_NAME  LIBDIR"/libmmfile_formats.so"
153 #define MMFILE_CODEC_SO_FILE_NAME   LIBDIR"/libmmfile_codecs.so"
154
155 int (*mmfile_format_open)(MMFileFormatContext **formatContext, MMFileSourceType *fileSrc);
156 int (*mmfile_format_read_stream)(MMFileFormatContext *formatContext);
157 int (*mmfile_format_read_frame)(MMFileFormatContext *formatContext, unsigned int timestamp, MMFileFormatFrame *frame);
158 int (*mmfile_format_read_tag)(MMFileFormatContext *formatContext);
159 int (*mmfile_format_close)(MMFileFormatContext *formatContext);
160 int (*mmfile_codec_open)(MMFileCodecContext **codecContext, int codecType, int codecId, MMFileCodecFrame *input);
161 int (*mmfile_codec_decode)(MMFileCodecContext *codecContext, MMFileCodecFrame *output);
162 int (*mmfile_codec_close)(MMFileCodecContext *codecContext);
163 int (*mmfile_format_get_frame)(const char *path, double timestamp, bool is_accurate, unsigned char **frame, int *size, int *width, int *height);
164 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);
165 #endif
166
167 #ifdef __MMFILE_DYN_LOADING__
168 static int _load_dynamic_functions(MMFILE_FUNC_HANDLE *pHandle)
169 {
170 /*      static int dll_func_initialized = 0; //disabled */
171
172         int ret = 0;
173
174         /* Get from function argument */
175         void *formatFuncHandle = NULL;
176         void *codecFuncHandle = NULL;
177
178         /* disabled
179         if (dll_func_initialized) {
180                 return 1;
181         }
182         */
183
184         formatFuncHandle = dlopen(MMFILE_FORMAT_SO_FILE_NAME, RTLD_LAZY);
185         if (!formatFuncHandle) {
186                 debug_error(DEBUG, "error: %s\n", "libmmfile_formats.so open error");
187                 ret = 0;
188                 goto exception;
189         }
190
191         mmfile_format_open                      = dlsym(formatFuncHandle, "mmfile_format_open");
192         mmfile_format_read_stream       = dlsym(formatFuncHandle, "mmfile_format_read_stream");
193         mmfile_format_read_frame        = dlsym(formatFuncHandle, "mmfile_format_read_frame");
194         mmfile_format_read_tag          = dlsym(formatFuncHandle, "mmfile_format_read_tag");
195         mmfile_format_close                     = dlsym(formatFuncHandle, "mmfile_format_close");
196
197         if (!mmfile_format_open ||
198             !mmfile_format_read_stream ||
199             !mmfile_format_read_frame ||
200             !mmfile_format_read_tag ||
201             !mmfile_format_close) {
202
203                 debug_error(DEBUG, "error: %s\n", "format function load error");
204                 ret = 0;
205                 goto exception;
206         }
207
208         /*closed at app termination.*/
209         /*dlclose (formatFuncHandle); */
210
211         codecFuncHandle = dlopen(MMFILE_CODEC_SO_FILE_NAME, RTLD_LAZY | RTLD_GLOBAL);
212         if (!codecFuncHandle) {
213                 debug_error(DEBUG, "error: %s\n", "libmmfile_codecs.so open error");
214                 ret = 0;
215                 goto exception;
216         }
217
218         mmfile_codec_open               = dlsym(codecFuncHandle, "mmfile_codec_open");
219         mmfile_codec_decode     = dlsym(codecFuncHandle, "mmfile_codec_decode");
220         mmfile_codec_close              = dlsym(codecFuncHandle, "mmfile_codec_close");
221
222         if (!mmfile_codec_open || !mmfile_codec_decode || !mmfile_codec_close) {
223                 debug_error(DEBUG, "error: %s\n", "codec function load error");
224                 ret = 0;
225                 goto exception;
226         }
227
228         /*closed at app termination.*/
229         /*dlclose (codecFuncHandle); */
230
231 /*      dll_func_initialized = 1; // disabled */
232
233         pHandle->codecFuncHandle = codecFuncHandle;
234         pHandle->formatFuncHandle = formatFuncHandle;
235
236         return 1;
237
238 exception:
239         if (formatFuncHandle) dlclose(formatFuncHandle);
240         if (codecFuncHandle)  dlclose(codecFuncHandle);
241
242         return ret;
243 }
244
245 static void _unload_dynamic_functions(MMFILE_FUNC_HANDLE *pHandle)
246 {
247         debug_fenter(RELEASE);
248
249         if (pHandle->formatFuncHandle) {
250                 dlclose(pHandle->formatFuncHandle);
251         }
252         if (pHandle->codecFuncHandle) {
253                 dlclose(pHandle->codecFuncHandle);
254         }
255
256         debug_fleave(RELEASE);
257 }
258
259
260 #endif /* __MMFILE_DYN_LOADING__ */
261
262 /**
263  * local functions.
264  */
265 static int
266 _is_file_exist(const char *filename)
267 {
268         int ret = 1;
269         if (filename) {
270                 const char *to_access = (strstr(filename, "file://") != NULL) ? filename + 7 : filename;
271                 ret = access(to_access, R_OK);
272                 if (ret != 0) {
273                         debug_error(DEBUG, "file [%s] not found.\n", to_access);
274                 }
275         }
276         return !ret;
277 }
278
279 static int
280 _info_set_attr_media(mmf_attrs_t *attrs, MMFileFormatContext *formatContext)
281 {
282         int ret = 0;
283         MMHandleType hattrs = CAST_MM_HANDLE(attrs);
284
285         if (formatContext->commandType == MM_FILE_TAG) {
286                 if (formatContext->title)                               mm_attrs_set_string_by_name(hattrs, MM_FILE_TAG_TITLE, formatContext->title);
287                 if (formatContext->artist)                              mm_attrs_set_string_by_name(hattrs, MM_FILE_TAG_ARTIST, formatContext->artist);
288                 if (formatContext->author)                      mm_attrs_set_string_by_name(hattrs, MM_FILE_TAG_AUTHOR, formatContext->author);
289                 if (formatContext->composer && formatContext->author == NULL)
290                         mm_attrs_set_string_by_name(hattrs, MM_FILE_TAG_AUTHOR, formatContext->composer);
291                 if (formatContext->album)                               mm_attrs_set_string_by_name(hattrs, MM_FILE_TAG_ALBUM, formatContext->album);
292                 if (formatContext->album_artist)                                mm_attrs_set_string_by_name(hattrs, MM_FILE_TAG_ALBUM_ARTIST, formatContext->album_artist);
293                 if (formatContext->copyright)                   mm_attrs_set_string_by_name(hattrs, MM_FILE_TAG_COPYRIGHT, formatContext->copyright);
294                 if (formatContext->description)                 mm_attrs_set_string_by_name(hattrs, MM_FILE_TAG_DESCRIPTION, formatContext->description);
295                 if (formatContext->comment)                     mm_attrs_set_string_by_name(hattrs, MM_FILE_TAG_COMMENT, formatContext->comment);
296                 if (formatContext->genre)                               mm_attrs_set_string_by_name(hattrs, MM_FILE_TAG_GENRE, formatContext->genre);
297                 if (formatContext->classification)              mm_attrs_set_string_by_name(hattrs, MM_FILE_TAG_CLASSIFICATION, formatContext->classification);
298                 if (formatContext->year)                                mm_attrs_set_string_by_name(hattrs, MM_FILE_TAG_DATE, formatContext->year);
299                 if (formatContext->tagTrackNum)         mm_attrs_set_string_by_name(hattrs, MM_FILE_TAG_TRACK_NUM, formatContext->tagTrackNum);
300                 if (formatContext->rating)                              mm_attrs_set_string_by_name(hattrs, MM_FILE_TAG_RATING, formatContext->rating);
301                 if (formatContext->conductor)                   mm_attrs_set_string_by_name(hattrs, MM_FILE_TAG_CONDUCTOR, formatContext->conductor);
302                 if (formatContext->recDate)                     mm_attrs_set_string_by_name(hattrs, MM_FILE_TAG_RECDATE, formatContext->recDate);
303                 if (formatContext->rotate)                              mm_attrs_set_string_by_name(hattrs, MM_FILE_TAG_ROTATE, formatContext->rotate);
304                 mm_attrs_set_double_by_name(hattrs, MM_FILE_TAG_LONGITUDE, formatContext->longitude);
305                 mm_attrs_set_double_by_name(hattrs, MM_FILE_TAG_LATIDUE, formatContext->latitude);
306                 mm_attrs_set_double_by_name(hattrs, MM_FILE_TAG_ALTIDUE, formatContext->altitude);
307                 mm_attrs_set_int_by_name(hattrs, MM_FILE_TAG_SYNCLYRICS_NUM, formatContext->syncLyricsNum);
308                 mm_attrs_set_int_by_name(hattrs, MM_FILE_TAG_CDIS, formatContext->cdis);
309                 mm_attrs_set_int_by_name(hattrs, MM_FILE_TAG_SMTA, formatContext->smta);
310
311                 mm_attrs_set_int_by_name(hattrs, MM_FILE_TAG_360, formatContext->is_360);
312                 mm_attrs_set_int_by_name(hattrs, MM_FILE_TAG_STITCHED_INFO, formatContext->stitched_info);
313
314                 if ((formatContext->syncLyricsNum > 0) && (formatContext->syncLyrics))
315                         mm_attrs_set_data_by_name(hattrs, MM_FILE_TAG_SYNCLYRICS, formatContext->syncLyrics, formatContext->syncLyricsNum);
316
317                 if (formatContext->unsyncLyrics)                mm_attrs_set_string_by_name(hattrs, MM_FILE_TAG_UNSYNCLYRICS, formatContext->unsyncLyrics);
318
319                 if (formatContext->artwork && formatContext->artworkSize > 0) {
320                         void *artworkCopy = NULL;
321                         artworkCopy = mmfile_malloc((formatContext->artworkSize));
322                         if (NULL != artworkCopy) {
323                                 memcpy(artworkCopy, formatContext->artwork, formatContext->artworkSize);
324                                 mm_attrs_set_data_by_name(hattrs, MM_FILE_TAG_ARTWORK, artworkCopy, formatContext->artworkSize);
325                                 mm_attrs_set_int_by_name(hattrs, MM_FILE_TAG_ARTWORK_SIZE, formatContext->artworkSize);
326                                 if (formatContext->artworkMime) mm_attrs_set_string_by_name(hattrs, MM_FILE_TAG_ARTWORK_MIME, formatContext->artworkMime);
327                         }
328                 }
329         } else if (formatContext->commandType == MM_FILE_CONTENTS) {
330                 /*get duration*/
331                 mm_attrs_set_int_by_name(hattrs, MM_FILE_CONTENT_DURATION, formatContext->duration);
332                 mm_attrs_set_int_by_name(hattrs, MM_FILE_CONTENT_AUDIO_TRACK_COUNT, formatContext->audioTotalTrackNum);
333                 mm_attrs_set_int_by_name(hattrs, MM_FILE_CONTENT_VIDEO_TRACK_COUNT, formatContext->videoTotalTrackNum);
334
335                 if (formatContext->videoTotalTrackNum > 0 &&
336                     formatContext->nbStreams > 0 &&
337                     formatContext->streams[MMFILE_VIDEO_STREAM]) {
338
339                         MMFileFormatStream *videoStream = formatContext->streams[MMFILE_VIDEO_STREAM];
340
341                         mm_attrs_set_int_by_name(hattrs, MM_FILE_CONTENT_VIDEO_FORMAT, formatContext->formatType);
342                         mm_attrs_set_int_by_name(hattrs, MM_FILE_CONTENT_VIDEO_CODEC, videoStream->codecId);
343                         mm_attrs_set_int_by_name(hattrs, MM_FILE_CONTENT_VIDEO_BITRATE, videoStream->bitRate);
344                         mm_attrs_set_int_by_name(hattrs, MM_FILE_CONTENT_VIDEO_FPS, videoStream->framePerSec);
345                         mm_attrs_set_int_by_name(hattrs, MM_FILE_CONTENT_VIDEO_WIDTH, videoStream->width);
346                         mm_attrs_set_int_by_name(hattrs, MM_FILE_CONTENT_VIDEO_HEIGHT, videoStream->height);
347
348                         if (formatContext->thumbNail && formatContext->thumbNail->frameData) {
349                                 void *thumbNailCopy = NULL;
350                                 thumbNailCopy = mmfile_malloc(formatContext->thumbNail->frameSize);
351
352                                 if (NULL != thumbNailCopy) {
353                                         memcpy(thumbNailCopy, formatContext->thumbNail->frameData, formatContext->thumbNail->frameSize);
354                                         mm_attrs_set_data_by_name(hattrs, MM_FILE_CONTENT_VIDEO_THUMBNAIL, thumbNailCopy, formatContext->thumbNail->frameSize);
355                                         mm_attrs_set_int_by_name(hattrs, MM_FILE_CONTENT_VIDEO_WIDTH, formatContext->thumbNail->frameWidth);
356                                         mm_attrs_set_int_by_name(hattrs, MM_FILE_CONTENT_VIDEO_HEIGHT, formatContext->thumbNail->frameHeight);
357                                 }
358                         }
359                 }
360
361                 if (formatContext->audioTotalTrackNum > 0 &&
362                     formatContext->nbStreams > 0 &&
363                     formatContext->streams[MMFILE_AUDIO_STREAM]) {
364
365                         MMFileFormatStream *audioStream = formatContext->streams[MMFILE_AUDIO_STREAM];
366
367                         mm_attrs_set_int_by_name(hattrs, MM_FILE_CONTENT_AUDIO_CODEC, audioStream->codecId);
368                         mm_attrs_set_int_by_name(hattrs, MM_FILE_CONTENT_AUDIO_CHANNELS, audioStream->nbChannel);
369                         mm_attrs_set_int_by_name(hattrs, MM_FILE_CONTENT_AUDIO_BITRATE, audioStream->bitRate);
370                         mm_attrs_set_int_by_name(hattrs, MM_FILE_CONTENT_AUDIO_SAMPLERATE, audioStream->samplePerSec);
371                         mm_attrs_set_int_by_name(hattrs, MM_FILE_CONTENT_AUDIO_BITPERSAMPLE, audioStream->bitPerSample);
372                 }
373         } else {
374                 ret = -1;
375         }
376
377         /*commit attrs*/
378         ret = mmf_attrs_commit((MMHandleType)hattrs);
379
380         return ret;
381 }
382
383 static int
384 _get_contents_info(mmf_attrs_t *attrs, MMFileSourceType *src, MMFILE_PARSE_INFO *parse)
385 {
386         MMFileFormatContext *formatContext = NULL;
387         MMFileCodecContext  *codecContext = NULL;
388         MMFileFormatFrame    frameContext = {0, };
389         MMFileCodecFrame     codecFrame = {0, };
390         MMFileCodecFrame     decodedFrame = {0, };
391
392         int ret = 0;
393
394         if (!src || !parse)
395                 return FILEINFO_ERROR_FILE_INTERNAL;
396
397         ret = mmfile_format_open(&formatContext, src);
398         if (MMFILE_FORMAT_FAIL == ret || formatContext == NULL) {
399                 debug_error(DEBUG, "error: mmfile_format_open\n");
400                 ret = FILEINFO_ERROR_FILE_INTERNAL;
401                 goto exception;
402         }
403
404         if (parse->type >= MM_FILE_PARSE_TYPE_NORMAL) {
405                 if (parse->type == MM_FILE_PARSE_TYPE_SAFE)
406                         formatContext->cdis = 1;
407                 ret = mmfile_format_read_stream(formatContext);
408                 if (MMFILE_FORMAT_FAIL == ret) {
409                         debug_error(DEBUG, "error: mmfile_format_read_stream\n");
410                         ret = FILEINFO_ERROR_FILE_INTERNAL;
411                         goto exception;
412                 }
413
414                 parse->audio_track_num = formatContext->audioTotalTrackNum;
415                 parse->video_track_num = formatContext->videoTotalTrackNum;
416
417                 /* check uhqa content*/
418                 if (formatContext->streams[MMFILE_AUDIO_STREAM] != NULL) {
419                         parse->is_uhqa = formatContext->streams[MMFILE_AUDIO_STREAM]->is_uhqa;
420                 } else {
421                         parse->is_uhqa = FALSE;
422                 }
423
424                 if (parse->type >= MM_FILE_PARSE_TYPE_ALL) {
425                         if (formatContext->videoTotalTrackNum > 0) {
426
427 /*why below code needed?
428 This API is for extracting some attributes not metadata(TAG). mm_file_create_content_attrs() use this API.
429 but MMFileUtilGetMetaDataFromMP4() Extract just TAG info. That is needed for mm_file_create_tag_attrs()*/
430 #if 0
431                                 if (parse->type != MM_FILE_PARSE_TYPE_SAFE) {
432                                         if (formatContext->formatType == MM_FILE_FORMAT_3GP || formatContext->formatType == MM_FILE_FORMAT_MP4) {
433                                                 MMFileUtilGetMetaDataFromMP4(formatContext);
434                                         }
435                                 }
436 #endif
437                                 MMFileFormatStream *videoStream = formatContext->streams[MMFILE_VIDEO_STREAM];
438                                 unsigned int timestamp = _SEEK_POINT_;
439
440                                 ret = mmfile_format_read_frame(formatContext, timestamp, &frameContext);
441                                 if (MMFILE_FORMAT_FAIL == ret) {
442                                         debug_error(DEBUG, "error: mmfile_format_read_frame\n");
443                                         ret = FILEINFO_ERROR_FILE_INTERNAL;
444                                         goto warning;
445                                 }
446
447                                 if (frameContext.bCompressed) {
448                                         codecFrame.frameDataSize = frameContext.frameSize;
449                                         codecFrame.width = frameContext.frameWidth;
450                                         codecFrame.height = frameContext.frameHeight;
451                                         codecFrame.frameData = frameContext.frameData;
452                                         codecFrame.configLen = frameContext.configLenth;
453                                         codecFrame.configData = frameContext.configData;
454                                         codecFrame.version = videoStream->version;
455
456                                         ret = mmfile_codec_open(&codecContext, MMFILE_VIDEO_DECODE, videoStream->codecId, &codecFrame);
457                                         if (MMFILE_FORMAT_FAIL == ret) {
458                                                 debug_error(DEBUG, "error: mmfile_codec_open\n");
459                                                 ret = FILEINFO_ERROR_FILE_INTERNAL;
460                                                 goto warning;
461                                         }
462
463                                         ret = mmfile_codec_decode(codecContext, &decodedFrame);
464                                         if (MMFILE_FORMAT_FAIL == ret) {
465                                                 debug_error(DEBUG, "error: mmfile_codec_decode\n");
466                                                 ret = FILEINFO_ERROR_FILE_INTERNAL;
467                                                 goto warning;
468                                         }
469
470                                         /* set video thumbnail */
471                                         formatContext->thumbNail = mmfile_malloc(sizeof(MMFileFormatFrame));
472                                         if (NULL == formatContext->thumbNail) {
473                                                 debug_error(DEBUG, "error: mmfile_malloc\n");
474                                                 ret = FILEINFO_ERROR_FILE_INTERNAL;
475                                                 goto warning;
476                                         }
477
478                                         formatContext->thumbNail->frameSize = decodedFrame.frameDataSize;
479                                         formatContext->thumbNail->frameWidth = decodedFrame.width;
480                                         formatContext->thumbNail->frameHeight = decodedFrame.height;
481                                         formatContext->thumbNail->frameData = decodedFrame.frameData;
482                                         formatContext->thumbNail->configLenth = 0;
483                                         formatContext->thumbNail->configData = NULL;
484                                 } else {
485                                         formatContext->thumbNail = mmfile_malloc(sizeof(MMFileFormatFrame));
486                                         if (NULL == formatContext->thumbNail) {
487                                                 debug_error(DEBUG, "error: mmfile_format_read_frame\n");
488                                                 ret = FILEINFO_ERROR_FILE_INTERNAL;
489                                                 goto warning;
490                                         }
491
492                                         formatContext->thumbNail->frameSize = frameContext.frameSize;
493                                         formatContext->thumbNail->frameWidth = frameContext.frameWidth;
494                                         formatContext->thumbNail->frameHeight = frameContext.frameHeight;
495                                         formatContext->thumbNail->frameData = frameContext.frameData;
496                                         formatContext->thumbNail->configLenth = 0;
497                                         formatContext->thumbNail->configData = NULL;
498                                 }
499                         }
500                 }
501         } else {
502                 /**
503                  * if MM_FILE_PARSE_TYPE_SIMPLE, just get number of each stream.
504                  */
505                 parse->audio_track_num = formatContext->audioTotalTrackNum;
506                 parse->video_track_num = formatContext->videoTotalTrackNum;
507         }
508
509 #ifdef __MMFILE_TEST_MODE__
510         mmfile_format_print_frame(&frameContext);
511 #endif
512
513         formatContext->commandType = MM_FILE_CONTENTS;
514
515         if (parse->type >= MM_FILE_PARSE_TYPE_NORMAL)
516                 _info_set_attr_media(attrs, formatContext);
517
518         if (frameContext.bCompressed) {
519                 if (frameContext.frameData) mmfile_free(frameContext.frameData);
520                 if (frameContext.configData) mmfile_free(frameContext.configData);
521
522                 if (decodedFrame.frameData) {
523                         mmfile_free(decodedFrame.frameData);
524                         formatContext->thumbNail->frameData = NULL;
525                 }
526                 if (decodedFrame.configData) {
527                         mmfile_free(decodedFrame.configData);
528                         formatContext->thumbNail->configData = NULL;
529                 }
530         } else {
531                 if (frameContext.frameData) {
532                         mmfile_free(frameContext.frameData);
533                         formatContext->thumbNail->frameData = NULL;
534                 }
535                 if (frameContext.configData) {
536                         mmfile_free(frameContext.configData);
537                         formatContext->thumbNail->configData = NULL;
538                 }
539         }
540
541         if (formatContext)  {
542                 mmfile_format_close(formatContext);
543         }
544         if (codecContext)   {
545                 mmfile_codec_close(codecContext);
546         }
547
548         return FILEINFO_ERROR_NONE;
549
550 warning:
551         formatContext->commandType = MM_FILE_CONTENTS;
552
553         if (frameContext.bCompressed) {
554                 if (frameContext.frameData)
555                         mmfile_free(frameContext.frameData);
556
557                 if (frameContext.configData)
558                         mmfile_free(frameContext.configData);
559
560                 if (decodedFrame.frameData) {
561                         mmfile_free(decodedFrame.frameData);
562                         if (formatContext->thumbNail)
563                                 formatContext->thumbNail->frameData = NULL;
564                 }
565
566                 if (decodedFrame.configData) {
567                         mmfile_free(decodedFrame.configData);
568                         if (formatContext->thumbNail)
569                                 formatContext->thumbNail->configData = NULL;
570                 }
571         } else {
572                 if (frameContext.frameData) {
573                         mmfile_free(frameContext.frameData);
574                         if (formatContext->thumbNail)
575                                 formatContext->thumbNail->frameData = NULL;
576                 }
577
578                 if (frameContext.configData) {
579                         mmfile_free(frameContext.configData);
580                         if (formatContext->thumbNail)
581                                 formatContext->thumbNail->configData = NULL;
582                 }
583         }
584
585         if (parse->type >= MM_FILE_PARSE_TYPE_NORMAL)
586                 _info_set_attr_media(attrs, formatContext);
587
588         if (formatContext)  {
589                 mmfile_format_close(formatContext);
590         }
591         if (codecContext)   {
592                 mmfile_codec_close(codecContext);
593         }
594         return FILEINFO_ERROR_NONE;
595
596
597 exception:
598         if (frameContext.bCompressed) {
599                 if (frameContext.frameData)
600                         mmfile_free(frameContext.frameData);
601
602                 if (frameContext.configData)
603                         mmfile_free(frameContext.configData);
604
605                 if (decodedFrame.frameData) {
606                         mmfile_free(decodedFrame.frameData);
607                         if (formatContext->thumbNail)
608                                 formatContext->thumbNail->frameData = NULL;
609                 }
610
611                 if (decodedFrame.configData) {
612                         mmfile_free(decodedFrame.configData);
613                         if (formatContext->thumbNail)
614                                 formatContext->thumbNail->configData = NULL;
615                 }
616         } else {
617                 if (frameContext.frameData) {
618                         mmfile_free(frameContext.frameData);
619                         if (formatContext->thumbNail)
620                                 formatContext->thumbNail->frameData = NULL;
621                 }
622
623                 if (frameContext.configData) {
624                         mmfile_free(frameContext.configData);
625                         if (formatContext->thumbNail)
626                                 formatContext->thumbNail->configData = NULL;
627                 }
628         }
629
630         if (formatContext)  {
631                 mmfile_format_close(formatContext);
632         }
633         /* if (codecContext)   { mmfile_codec_close(codecContext); } */ /*dead code*/
634
635         return ret;
636 }
637
638
639 static int
640 _get_tag_info(mmf_attrs_t *attrs, MMFileSourceType *src)
641 {
642         MMFileFormatContext *formatContext = NULL;
643         int ret = 0;
644
645         ret = mmfile_format_open(&formatContext, src);
646         if (MMFILE_FORMAT_FAIL == ret || formatContext == NULL) {
647                 debug_error(DEBUG, "error: mmfile_format_open\n");
648                 ret = FILEINFO_ERROR_FILE_INTERNAL;
649                 goto exception;
650         }
651
652         ret = mmfile_format_read_tag(formatContext);
653         if (MMFILE_FORMAT_FAIL == ret) {
654                 debug_warning(DEBUG, "reading tag is fail\n");
655                 ret = FILEINFO_ERROR_FILE_INTERNAL;
656                 goto exception;
657         }
658
659         formatContext->commandType = MM_FILE_TAG;
660
661         _info_set_attr_media(attrs, formatContext);
662
663         if (formatContext)  {
664                 mmfile_format_close(formatContext);
665         }
666
667         return FILEINFO_ERROR_NONE;
668
669
670 exception:
671         if (formatContext)  {
672                 mmfile_format_close(formatContext);
673         }
674
675         return FILEINFO_ERROR_FILE_INTERNAL;
676 }
677
678
679 /**
680  * global functions.
681  */
682 int mm_file_get_attrs(MMHandleType attrs, char **err_attr_name, const char *first_attribute_name, ...)
683 {
684         int ret = FILEINFO_ERROR_NONE;
685         va_list var_args;
686
687         if (!attrs) {
688                 debug_error(DEBUG, "Invalid arguments [attrs 0]\n");
689                 return FILEINFO_ERROR_INVALID_ARGUMENT;
690         }
691
692         if (first_attribute_name == NULL) {
693                 debug_error(DEBUG, "Invalid arguments [first_attribute_name null]\n");
694                 return FILEINFO_ERROR_INVALID_ARGUMENT;
695         }
696
697         /* get requested attributes */
698         va_start(var_args, first_attribute_name);
699         ret = mm_attrs_get_valist(attrs, err_attr_name, first_attribute_name, var_args);
700         va_end(var_args);
701
702         if (ret != FILEINFO_ERROR_NONE) {
703                 if (err_attr_name) {
704                         debug_error(DEBUG, "failed to get %s\n", *err_attr_name);
705                 }
706         }
707
708         return ret;
709 }
710
711 int mm_file_get_synclyrics_info(MMHandleType tag_attrs, int index, unsigned long *time_info, char **lyrics)
712 {
713         int ret = FILEINFO_ERROR_NONE;
714         AvSynclyricsInfo *sync_lyric_item = NULL;
715         GList *synclyrics_list = NULL;
716
717         debug_fenter(RELEASE);
718
719         if ((mmf_attrs_t *)tag_attrs == NULL) {
720                 debug_error(DEBUG, "invalid handle");
721                 return FILEINFO_ERROR_INVALID_ARGUMENT;
722         }
723
724         ret = mm_attrs_get_data_by_name(tag_attrs, MM_FILE_TAG_SYNCLYRICS, (void **)&synclyrics_list);
725         if (ret != FILEINFO_ERROR_NONE) {
726                 debug_warning(RELEASE, "get data fail");
727                 return ret;
728         }
729
730         if (synclyrics_list != NULL) {
731
732                 sync_lyric_item = (AvSynclyricsInfo *)g_list_nth_data(synclyrics_list, index);
733
734                 if (sync_lyric_item == NULL) {
735                         debug_warning(RELEASE, "synclyric item is NULL");
736                         return FILEINFO_ERROR_ATTR_NOT_EXIST;
737                 }
738
739                 *time_info = sync_lyric_item->time_info;
740                 *lyrics = sync_lyric_item->lyric_info;
741
742         } else {
743                 debug_warning(RELEASE, "synclyrics_list is NULL");
744                 return FILEINFO_ERROR_ATTR_NOT_EXIST;
745         }
746
747         return ret;
748
749 }
750
751 int mm_file_create_tag_attrs(MMHandleType *tag_attrs, const char *filename)
752 {
753         int ret = FILEINFO_ERROR_NONE;
754         mmf_attrs_t *attrs = NULL;
755         MMFileSourceType src;
756
757         debug_fenter(RELEASE);
758
759         /* Check argument here */
760         if (tag_attrs == NULL) {
761                 debug_error(DEBUG, "Invalid arguments [tag null]\n");
762                 return FILEINFO_ERROR_INVALID_ARGUMENT;
763         }
764         if (filename == NULL) {
765                 debug_error(DEBUG, "Invalid arguments [filename null]\n");
766                 return FILEINFO_ERROR_INVALID_ARGUMENT;
767         }
768         if (strlen(filename) == 0)      {
769                 debug_error(DEBUG, "Invalid arguments [filename size 0]\n");
770                 return FILEINFO_ERROR_INVALID_ARGUMENT;
771         }
772
773
774 #ifdef __MMFILE_DYN_LOADING__
775         MMFILE_FUNC_HANDLE func_handle;
776
777         ret = _load_dynamic_functions(&func_handle);
778         if (ret == 0) {
779                 debug_error(DEBUG, "load library error\n");
780                 return FILEINFO_ERROR_FILE_INTERNAL;
781         }
782 #endif
783
784         /*set source file infomation*/
785         MM_FILE_SET_MEDIA_FILE_SRC(src, filename);
786
787         ret = _is_file_exist(filename);
788         if (!ret) {
789                 ret = FILEINFO_ERROR_FILE_NOT_FOUND;
790                 goto END;
791         }
792
793         /*set attrs*/
794         attrs = (mmf_attrs_t *) mmf_attrs_new_from_data("tag", g_tag_attrs, ARRAY_SIZE(g_tag_attrs), NULL, NULL);
795         if (!attrs) {
796                 debug_error(DEBUG, "attribute internal error.\n");
797                 ret = FILEINFO_ERROR_FILE_INTERNAL;
798                 goto END;
799         }
800
801         ret = _get_tag_info(attrs, &src);
802         if (ret != FILEINFO_ERROR_NONE) {
803                 mmf_attrs_free((MMHandleType)attrs);
804                 attrs = NULL;
805                 debug_error(DEBUG, "failed to get tag: %s\n", filename);
806         }
807
808         *tag_attrs = (MMHandleType)attrs;
809
810 END:
811 #ifdef __MMFILE_DYN_LOADING__
812         _unload_dynamic_functions(&func_handle);
813 #endif
814
815         debug_fleave(RELEASE);
816
817         return ret;
818 }
819
820
821 EXPORT_API
822 int mm_file_destroy_tag_attrs(MMHandleType tag_attrs)
823 {
824         void *artwork = NULL;
825         GList *synclyrics_list = NULL;
826         int ret = FILEINFO_ERROR_NONE;
827
828         debug_fenter(RELEASE);
829
830         if ((mmf_attrs_t *)tag_attrs == NULL) {
831                 debug_error(DEBUG, "invalid handle.\n");
832                 return FILEINFO_ERROR_INVALID_ARGUMENT;
833         }
834
835         ret = mm_attrs_get_data_by_name(tag_attrs, MM_FILE_TAG_ARTWORK, &artwork);
836
837         if (artwork != NULL) {
838                 mmfile_free(artwork);
839         }
840
841         ret = mm_attrs_get_data_by_name(tag_attrs, MM_FILE_TAG_SYNCLYRICS, (void **)&synclyrics_list);
842
843         if (synclyrics_list != NULL) {
844                 mm_file_free_synclyrics_list(synclyrics_list);
845         }
846
847         mmf_attrs_free(tag_attrs);
848
849         debug_fleave(RELEASE);
850
851         return ret;
852 }
853
854 EXPORT_API
855 int mm_file_create_content_attrs(MMHandleType *contents_attrs, const char *filename)
856 {
857         mmf_attrs_t *attrs = NULL;
858         MMFileSourceType src = {0, };
859         MMFILE_PARSE_INFO parse = {0, };
860         int ret = 0;
861
862         debug_fenter(RELEASE);
863
864         /* Check argument here */
865         if (contents_attrs == NULL) {
866                 debug_error(DEBUG, "Invalid arguments [contents null]\n");
867                 return FILEINFO_ERROR_INVALID_ARGUMENT;
868         }
869         if (filename == NULL) {
870                 debug_error(DEBUG, "Invalid arguments [filename null]\n");
871                 return FILEINFO_ERROR_INVALID_ARGUMENT;
872         }
873         if (strlen(filename) == 0)      {
874                 debug_error(DEBUG, "Invalid arguments [filename size 0]\n");
875                 return FILEINFO_ERROR_INVALID_ARGUMENT;
876         }
877
878
879 #ifdef __MMFILE_DYN_LOADING__
880         MMFILE_FUNC_HANDLE func_handle;
881
882 #ifdef CHECK_TIME
883         int64_t ti;
884         ti = gettime();
885 #endif
886
887         ret = _load_dynamic_functions(&func_handle);
888         if (ret == 0) {
889                 debug_error(DEBUG, "load library error\n");
890                 return FILEINFO_ERROR_FILE_INTERNAL;
891         }
892
893 #ifdef CHECK_TIME
894         debug_msg(DEBUG, "_load_dynamic_functions() = %lld\n", gettime() - ti);
895 #endif
896
897 #endif
898
899         /*set source file infomation*/
900         MM_FILE_SET_MEDIA_FILE_SRC(src, filename);
901
902         ret = _is_file_exist(filename);
903         if (!ret) {
904                 ret = FILEINFO_ERROR_FILE_NOT_FOUND;
905                 goto END;
906         }
907
908         /*set attrs*/
909         attrs = (mmf_attrs_t *) mmf_attrs_new_from_data("content", g_content_attrs, ARRAY_SIZE(g_content_attrs), NULL, NULL);
910         if (!attrs) {
911                 debug_error(DEBUG, "attribute internal error.\n");
912                 ret = FILEINFO_ERROR_FILE_INTERNAL;
913                 goto END;
914         }
915
916
917         parse.type = MM_FILE_PARSE_TYPE_ALL;
918         ret = _get_contents_info(attrs, &src, &parse);
919         if (ret != FILEINFO_ERROR_NONE) {
920                 mmf_attrs_free((MMHandleType)attrs);
921                 attrs = NULL;
922                 debug_error(DEBUG, "failed to get contents: %s\n", filename);
923         }
924
925         *contents_attrs = (MMHandleType) attrs;
926
927
928 END:
929 #ifdef __MMFILE_DYN_LOADING__
930
931 #ifdef CHECK_TIME
932         ti = gettime();
933 #endif
934
935         _unload_dynamic_functions(&func_handle);
936
937 #ifdef CHECK_TIME
938         debug_msg(DEBUG, "_unload_dynamic_functions() = %lld\n", gettime() - ti);
939 #endif
940
941 #endif
942
943         debug_fleave(RELEASE);
944
945         return ret;
946 }
947
948
949 EXPORT_API
950 int mm_file_create_tag_attrs_from_memory(MMHandleType *tag_attrs, const void *data, unsigned int size, int format)
951 {
952         mmf_attrs_t *attrs = NULL;
953         MMFileSourceType src;
954         /*MMFILE_PARSE_INFO parse = {0, };*/
955         int ret = 0;
956
957         debug_fenter(RELEASE);
958
959         /* Check argument here */
960         if (tag_attrs == NULL || data == NULL) {
961                 debug_error(DEBUG, "Invalid arguments\n");
962                 return FILEINFO_ERROR_INVALID_ARGUMENT;
963         }
964
965 #ifdef __MMFILE_DYN_LOADING__
966         MMFILE_FUNC_HANDLE func_handle;
967
968         ret = _load_dynamic_functions(&func_handle);
969         if (ret == 0) {
970                 debug_error(DEBUG, "load library error\n");
971                 return FILEINFO_ERROR_FILE_INTERNAL;
972         }
973 #endif
974
975         MM_FILE_SET_MEDIA_MEM_SRC(src, data, size, format);
976
977         /*set attrs*/
978         attrs = (mmf_attrs_t *) mmf_attrs_new_from_data("tag", g_tag_attrs, ARRAY_SIZE(g_tag_attrs), NULL, NULL);
979         if (!attrs) {
980                 debug_error(DEBUG, "attribute internal error.\n");
981                 ret = FILEINFO_ERROR_FILE_INTERNAL;
982                 goto END;
983         }
984
985         /*parse.type = MM_FILE_PARSE_TYPE_ALL;*/
986         ret = _get_tag_info(attrs, &src);
987         if (ret != FILEINFO_ERROR_NONE) {
988                 mmf_attrs_free((MMHandleType)attrs);
989                 attrs = NULL;
990                 debug_error(DEBUG, "failed to get tag");
991         }
992
993         *tag_attrs = (MMHandleType)attrs;
994
995 END:
996 #ifdef __MMFILE_DYN_LOADING__
997         _unload_dynamic_functions(&func_handle);
998 #endif
999
1000         debug_fleave(RELEASE);
1001
1002         return ret;
1003 }
1004
1005
1006 EXPORT_API
1007 int mm_file_create_content_attrs_from_memory(MMHandleType *contents_attrs, const void *data, unsigned int size, int format)
1008 {
1009         mmf_attrs_t *attrs = NULL;
1010         MMFileSourceType src;
1011         MMFILE_PARSE_INFO parse = {0, };
1012         int ret = 0;
1013
1014         debug_fenter(RELEASE);
1015
1016         /* Check argument here */
1017         if (contents_attrs == NULL || data == NULL) {
1018                 debug_error(DEBUG, "Invalid arguments\n");
1019                 return FILEINFO_ERROR_INVALID_ARGUMENT;
1020         }
1021
1022 #ifdef __MMFILE_DYN_LOADING__
1023         MMFILE_FUNC_HANDLE func_handle;
1024
1025         ret = _load_dynamic_functions(&func_handle);
1026         if (ret == 0) {
1027                 debug_error(DEBUG, "load library error\n");
1028                 return FILEINFO_ERROR_FILE_INTERNAL;
1029         }
1030 #endif
1031
1032         MM_FILE_SET_MEDIA_MEM_SRC(src, data, size, format);
1033
1034         /*set attrs*/
1035         attrs = (mmf_attrs_t *) mmf_attrs_new_from_data("content", g_content_attrs, ARRAY_SIZE(g_content_attrs), NULL, NULL);
1036         if (!attrs) {
1037                 debug_error(DEBUG, "attribute internal error.\n");
1038                 ret = FILEINFO_ERROR_FILE_INTERNAL;
1039                 goto END;
1040         }
1041
1042         parse.type = MM_FILE_PARSE_TYPE_ALL;
1043         ret = _get_contents_info(attrs, &src, &parse);
1044         if (ret != FILEINFO_ERROR_NONE) {
1045                 mmf_attrs_free((MMHandleType)attrs);
1046                 attrs = NULL;
1047                 debug_error(DEBUG, "failed to get contents");
1048         }
1049
1050         *contents_attrs = (MMHandleType)attrs;
1051
1052 END:
1053 #ifdef __MMFILE_DYN_LOADING__
1054         _unload_dynamic_functions(&func_handle);
1055 #endif
1056
1057         debug_fleave(RELEASE);
1058
1059         return ret;
1060 }
1061
1062
1063 EXPORT_API
1064 int mm_file_destroy_content_attrs(MMHandleType contents_attrs)
1065 {
1066         void *thumbnail = NULL;
1067         int ret = FILEINFO_ERROR_NONE;
1068
1069         debug_fenter(RELEASE);
1070
1071         if ((mmf_attrs_t *)contents_attrs == NULL) {
1072                 debug_error(DEBUG, "invalid handle.\n");
1073                 return FILEINFO_ERROR_INVALID_ARGUMENT;
1074         }
1075
1076         ret = mm_attrs_get_data_by_name(contents_attrs, MM_FILE_CONTENT_VIDEO_THUMBNAIL, &thumbnail);
1077         if (thumbnail != NULL) {
1078                 mmfile_free(thumbnail);
1079         }
1080
1081         mmf_attrs_free(contents_attrs);
1082
1083         debug_fleave(RELEASE);
1084
1085         return ret;
1086 }
1087
1088
1089 EXPORT_API
1090 int mm_file_get_stream_info(const char *filename, int *audio_stream_num, int *video_stream_num)
1091 {
1092         MMFileSourceType     src = {0, };
1093         MMFILE_PARSE_INFO    parse = {0, };
1094
1095         int ret = 0;
1096
1097         debug_fenter(RELEASE);
1098
1099         if (filename == NULL || strlen(filename) == 0 || audio_stream_num == NULL || video_stream_num == NULL) {
1100                 debug_error(DEBUG, "Invalid arguments\n");
1101                 return FILEINFO_ERROR_INVALID_ARGUMENT;
1102         }
1103
1104 #ifdef __MMFILE_DYN_LOADING__
1105         MMFILE_FUNC_HANDLE func_handle;
1106
1107         ret = _load_dynamic_functions(&func_handle);
1108         if (ret == 0) {
1109                 debug_error(DEBUG, "load library error\n");
1110                 return FILEINFO_ERROR_FILE_INTERNAL;
1111         }
1112 #endif
1113
1114         /*set source file infomation*/
1115         MM_FILE_SET_MEDIA_FILE_SRC(src, filename);
1116
1117         ret = _is_file_exist(filename);
1118         if (!ret) {
1119                 ret = FILEINFO_ERROR_FILE_NOT_FOUND;
1120                 goto END;
1121         }
1122
1123         parse.type = MM_FILE_PARSE_TYPE_SIMPLE;
1124         ret = _get_contents_info(NULL, &src, &parse);
1125         if (ret != FILEINFO_ERROR_NONE) {
1126                 debug_error(DEBUG, "failed to get stream info: %s\n", filename);
1127         } else {
1128                 if (parse.audio_track_num == 0 && parse.video_track_num == 0) {
1129                         debug_error(DEBUG, "empty header. retry to get stream info: %s\n", filename);
1130                         parse.type = MM_FILE_PARSE_TYPE_NORMAL;
1131                         ret = _get_contents_info(NULL, &src, &parse);
1132                 }
1133         }
1134
1135         /*set number of each stream*/
1136         *audio_stream_num = parse.audio_track_num;
1137         *video_stream_num = parse.video_track_num;
1138
1139 END:
1140 #ifdef __MMFILE_DYN_LOADING__
1141         _unload_dynamic_functions(&func_handle);
1142 #endif
1143
1144         debug_fleave(RELEASE);
1145
1146         return ret;
1147 }
1148
1149 EXPORT_API
1150 int mm_file_create_content_attrs_simple(MMHandleType *contents_attrs, const char *filename)
1151 {
1152         mmf_attrs_t *attrs = NULL;
1153         MMFileSourceType src = {0, };
1154         MMFILE_PARSE_INFO parse = {0, };
1155         int ret = 0;
1156
1157         debug_fenter(RELEASE);
1158
1159 #ifdef __MMFILE_DYN_LOADING__
1160         MMFILE_FUNC_HANDLE func_handle;
1161
1162         ret = _load_dynamic_functions(&func_handle);
1163         if (ret == 0) {
1164                 debug_error(DEBUG, "load library error\n");
1165                 return FILEINFO_ERROR_FILE_INTERNAL;
1166         }
1167 #endif
1168         if (filename == NULL) {
1169                 ret =  FILEINFO_ERROR_INVALID_ARGUMENT;
1170                 goto END;
1171         } else {
1172                 if (strlen(filename) == 0) {
1173                         ret =  FILEINFO_ERROR_INVALID_ARGUMENT;
1174                         goto END;
1175                 }
1176         }
1177
1178         /*set source file infomation*/
1179         MM_FILE_SET_MEDIA_FILE_SRC(src, filename);
1180
1181         ret = _is_file_exist(filename);
1182         if (!ret) {
1183                 ret = FILEINFO_ERROR_FILE_NOT_FOUND;
1184                 goto END;
1185         }
1186
1187         /*set attrs*/
1188         attrs = (mmf_attrs_t *) mmf_attrs_new_from_data("content", g_content_attrs, ARRAY_SIZE(g_content_attrs), NULL, NULL);
1189         if (!attrs) {
1190                 debug_error(DEBUG, "attribute internal error.\n");
1191                 ret = FILEINFO_ERROR_FILE_INTERNAL;
1192                 goto END;
1193         }
1194
1195         parse.type = MM_FILE_PARSE_TYPE_NORMAL;
1196         ret = _get_contents_info(attrs, &src, &parse);
1197         if (ret != FILEINFO_ERROR_NONE) {
1198                 mmf_attrs_free((MMHandleType)attrs);
1199                 attrs = NULL;
1200                 debug_error(DEBUG, "failed to get contents: %s\n", filename);
1201         }
1202
1203         *contents_attrs = (MMHandleType) attrs;
1204
1205 END:
1206 #ifdef __MMFILE_DYN_LOADING__
1207         _unload_dynamic_functions(&func_handle);
1208 #endif
1209
1210         debug_fleave(RELEASE);
1211
1212         return ret;
1213 }
1214
1215 EXPORT_API
1216 int mm_file_create_content_attrs_safe(MMHandleType *contents_attrs, const char *filename)
1217 {
1218         mmf_attrs_t *attrs = NULL;
1219         MMFileSourceType src = {0, };
1220         MMFILE_PARSE_INFO parse = {0, };
1221         int ret = 0;
1222
1223         debug_fenter(RELEASE);
1224
1225 #ifdef __MMFILE_DYN_LOADING__
1226         MMFILE_FUNC_HANDLE func_handle;
1227
1228         ret = _load_dynamic_functions(&func_handle);
1229         if (ret == 0) {
1230                 debug_error(DEBUG, "load library error\n");
1231                 return FILEINFO_ERROR_FILE_INTERNAL;
1232         }
1233 #endif
1234         if (filename == NULL) {
1235                 ret = FILEINFO_ERROR_INVALID_ARGUMENT;
1236                 goto END;
1237         } else {
1238                 if (strlen(filename) == 0) {
1239                         ret = FILEINFO_ERROR_INVALID_ARGUMENT;
1240                         goto END;
1241                 }
1242         }
1243
1244         /*set source file infomation*/
1245         MM_FILE_SET_MEDIA_FILE_SRC(src, filename);
1246
1247         ret = _is_file_exist(filename);
1248         if (!ret) {
1249                 ret = FILEINFO_ERROR_FILE_NOT_FOUND;
1250                 goto END;
1251         }
1252
1253         /*set attrs*/
1254         attrs = (mmf_attrs_t *) mmf_attrs_new_from_data("content", g_content_attrs, ARRAY_SIZE(g_content_attrs), NULL, NULL);
1255         if (!attrs) {
1256                 debug_error(DEBUG, "attribute internal error.\n");
1257                 ret = FILEINFO_ERROR_FILE_INTERNAL;
1258                 goto END;
1259         }
1260
1261         parse.type = MM_FILE_PARSE_TYPE_SAFE;
1262         ret = _get_contents_info(attrs, &src, &parse);
1263         if (ret != FILEINFO_ERROR_NONE) {
1264                 mmf_attrs_free((MMHandleType)attrs);
1265                 attrs = NULL;
1266                 debug_error(DEBUG, "failed to get contents: %s\n", filename);
1267         }
1268
1269         *contents_attrs = (MMHandleType) attrs;
1270
1271 END:
1272 #ifdef __MMFILE_DYN_LOADING__
1273         _unload_dynamic_functions(&func_handle);
1274 #endif
1275
1276         debug_fleave(RELEASE);
1277
1278         return ret;
1279 }
1280
1281 EXPORT_API
1282 int mm_file_get_video_frame(const char *path, double timestamp, bool is_accurate, unsigned char **frame, int *size, int *width, int *height)
1283 {
1284         int ret = 0;
1285         void *formatFuncHandle = NULL;
1286
1287         if (path == NULL) {
1288                 debug_error(DEBUG, "Invalid arguments [Path is Null]\n");
1289                 return FILEINFO_ERROR_INVALID_ARGUMENT;
1290         }
1291
1292 #ifdef __MMFILE_DYN_LOADING__
1293         /* Get from function argument */
1294         formatFuncHandle = dlopen(MMFILE_FORMAT_SO_FILE_NAME, RTLD_LAZY);
1295         if (!formatFuncHandle) {
1296                 debug_error(DEBUG, "error : dlopen");
1297                 goto exception;
1298         }
1299
1300         mmfile_format_get_frame = dlsym(formatFuncHandle, "mmfile_format_get_frame");
1301         if (!mmfile_format_get_frame) {
1302                 debug_error(DEBUG, "error : load library");
1303                 goto exception;
1304         }
1305 #endif
1306
1307         debug_msg(RELEASE, "file path [%s] is_accurate [%d]", path, is_accurate);
1308
1309         ret = mmfile_format_get_frame(path, timestamp, is_accurate, frame, size, width, height);
1310         if (ret  == MMFILE_FORMAT_FAIL) {
1311                 debug_error(DEBUG, "error : get frame");
1312                 goto exception;
1313         }
1314
1315         if (formatFuncHandle) dlclose(formatFuncHandle);
1316
1317         return FILEINFO_ERROR_NONE;
1318
1319 exception:
1320         if (formatFuncHandle) dlclose(formatFuncHandle);
1321
1322         return FILEINFO_ERROR_FILE_INTERNAL;
1323 }
1324
1325 EXPORT_API
1326 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)
1327 {
1328         int ret = 0;
1329         void *formatFuncHandle = NULL;
1330
1331         if (data == NULL) {
1332                 debug_error(DEBUG, "Invalid arguments [data is Null]\n");
1333                 return FILEINFO_ERROR_INVALID_ARGUMENT;
1334         }
1335
1336         if (datasize == 0) {
1337                 debug_error(DEBUG, "Invalid arguments [datasize is zero]\n");
1338                 return FILEINFO_ERROR_INVALID_ARGUMENT;
1339         }
1340
1341 #ifdef __MMFILE_DYN_LOADING__
1342         /* Get from function argument */
1343         formatFuncHandle = dlopen(MMFILE_FORMAT_SO_FILE_NAME, RTLD_LAZY);
1344         if (!formatFuncHandle) {
1345                 debug_error(DEBUG, "error : dlopen");
1346                 goto exception;
1347         }
1348
1349         mmfile_format_get_frame_from_memory = dlsym(formatFuncHandle, "mmfile_format_get_frame_from_memory");
1350         if (!mmfile_format_get_frame_from_memory) {
1351                 debug_error(DEBUG, "error : load library");
1352                 goto exception;
1353         }
1354 #endif
1355
1356         debug_msg(RELEASE, "data [%p], data_size[%d], is_accurate [%d]", data, datasize, is_accurate);
1357
1358         ret = mmfile_format_get_frame_from_memory(data, datasize, timestamp, is_accurate, frame, size, width, height);
1359         if (ret  == MMFILE_FORMAT_FAIL) {
1360                 debug_error(DEBUG, "error : get frame");
1361                 goto exception;
1362         }
1363
1364         if (formatFuncHandle) dlclose(formatFuncHandle);
1365
1366         return FILEINFO_ERROR_NONE;
1367
1368 exception:
1369         if (formatFuncHandle) dlclose(formatFuncHandle);
1370
1371         return FILEINFO_ERROR_FILE_INTERNAL;
1372 }
1373
1374 EXPORT_API
1375 int mm_file_check_uhqa(const char *filename, bool *is_uhqa)
1376 {
1377         mmf_attrs_t *attrs = NULL;
1378         MMFileSourceType src = {0, };
1379         MMFILE_PARSE_INFO parse = {0, };
1380         int ret = 0;
1381
1382 #ifdef __MMFILE_DYN_LOADING__
1383         MMFILE_FUNC_HANDLE func_handle;
1384
1385         ret = _load_dynamic_functions(&func_handle);
1386         if (ret == 0) {
1387                 debug_error(DEBUG, "load library error\n");
1388                 return FILEINFO_ERROR_FILE_INTERNAL;
1389         }
1390 #endif
1391         if (filename == NULL) {
1392                 ret = FILEINFO_ERROR_INVALID_ARGUMENT;
1393                 goto END;
1394         } else {
1395                 if (strlen(filename) == 0) {
1396                         ret = FILEINFO_ERROR_INVALID_ARGUMENT;
1397                         goto END;
1398                 }
1399         }
1400
1401         /*set source file infomation*/
1402         MM_FILE_SET_MEDIA_FILE_SRC(src, filename);
1403
1404         ret = _is_file_exist(filename);
1405         if (!ret) {
1406                 ret = FILEINFO_ERROR_FILE_NOT_FOUND;
1407                 goto END;
1408         }
1409
1410         /*set attrs*/
1411         attrs = (mmf_attrs_t *) mmf_attrs_new_from_data("content", g_content_attrs, ARRAY_SIZE(g_content_attrs), NULL, NULL);
1412         if (!attrs) {
1413                 debug_error(DEBUG, "attribute internal error.\n");
1414                 ret = FILEINFO_ERROR_FILE_INTERNAL;
1415                 goto END;
1416         }
1417
1418         parse.type = MM_FILE_PARSE_TYPE_NORMAL;
1419         ret = _get_contents_info(attrs, &src, &parse);
1420         if (ret == FILEINFO_ERROR_NONE) {
1421                 *is_uhqa = parse.is_uhqa;
1422         } else {
1423                 debug_error(DEBUG, "_get_contents_info failed\n");
1424                 *is_uhqa = FALSE;
1425         }
1426
1427         mmf_attrs_free((MMHandleType)attrs);
1428         attrs = NULL;
1429
1430 END:
1431 #ifdef __MMFILE_DYN_LOADING__
1432         _unload_dynamic_functions(&func_handle);
1433 #endif
1434
1435         debug_fleave(RELEASE);
1436
1437         return ret;
1438 }