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