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