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