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