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