add support ape format
[platform/core/multimedia/libmm-fileinfo.git] / formats / ffmpeg / mm_file_formats.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 <string.h>
24 #include <stdlib.h>
25 #include "mm_file_debug.h"
26 #include "mm_file_format_private.h"
27 #include "mm_file_utils.h"
28
29 #define _MMF_FILE_FILEEXT_MAX 128
30
31 #define MMFILE_EXT_MP4          0x6D7034
32 #define MMFILE_EXT_MPEG4        0x6D70656734
33 #define MMFILE_EXT_M4A          0x6D3461
34 #define MMFILE_EXT_MPG          0x6D7067
35 #define MMFILE_EXT_MPG4         0x6D706734
36 #define MMFILE_EXT_M4V          0x6D3476
37 #define MMFILE_EXT_3GP          0x336770
38 #define MMFILE_EXT_AMR          0x616D72
39 #define MMFILE_EXT_AWB          0x617762
40 #define MMFILE_EXT_WAV          0x776176
41 #define MMFILE_EXT_MID          0x6D6964
42 #define MMFILE_EXT_MIDI         0x6D696D69
43 #define MMFILE_EXT_SPM          0x73706D
44 #define MMFILE_EXT_MP3          0x6D7033
45 #define MMFILE_EXT_AAC          0x616163
46 #define MMFILE_EXT_XMF          0x786D66
47 #define MMFILE_EXT_MXMF         0x6D786D66
48 #define MMFILE_EXT_MMF          0x6D6D66
49 #define MMFILE_EXT_MA2          0x6D6132
50 #define MMFILE_EXT_IMY          0x696D79
51 #define MMFILE_EXT_AVI          0x617669
52 #define MMFILE_EXT_DIVX         0x64697678
53 #define MMFILE_EXT_ASF          0x617366
54 #define MMFILE_EXT_ASX          0x617378
55 #define MMFILE_EXT_WMA          0x776D61
56 #define MMFILE_EXT_WMV          0x776D76
57 #define MMFILE_EXT_OGG          0x6F6767
58 #define MMFILE_EXT_MKV          0x6D6B76
59 #define MMFILE_EXT_MKA          0x6D6B61
60 #define MMFILE_EXT_MOV          0x6D6F76
61 #define MMFILE_EXT_FLAC         0x666C6163
62 #define MMFILE_EXT_FLV          0x666C76
63 #define MMFILE_EXT_AIF          0x616966
64 #define MMFILE_EXT_AIFF         0x61696666
65 #define MMFILE_EXT_RMVB         0x726D7662
66 #define MMFILE_EXT_RM           0x726D
67 #define MMFILE_EXT_M2TS         0x6D327473
68 #define MMFILE_EXT_MTS          0x6D7473
69 #define MMFILE_EXT_TS           0x7473
70 #define MMFILE_EXT_TP           0x7470
71 #define MMFILE_EXT_MPEG         0x6D706567
72 #define MMFILE_EXT_WEBM         0x7765626D
73 #define MMFILE_EXT_TTS          0x747473
74 #define MMFILE_EXT_TRP          0x747270
75 #define MMFILE_EXT_3M           0x336D
76 #define MMFILE_EXT_26L          0x32366C
77 #define MMFILE_EXT_264          0x323634
78 #define MMFILE_EXT_APE          0x617065
79
80 const struct {
81         int (*Open)(MMFileFormatContext *fileContext);
82         int (*Valid)(MMFileIOHandle *pFileIO, const char *mmfileuri, int mp3FrameCnt);
83 } MMFileFunc[MM_FILE_FORMAT_NUM + 1] = {
84         {mmfile_format_open_ffmpg, MMFileFormatIsValidMP4},                     /* 3GP */
85         {mmfile_format_open_ffmpg, MMFileFormatIsValidASF},                     /* ASF */
86         {mmfile_format_open_ffmpg, MMFileFormatIsValidAVI},                     /* AVI */
87         {mmfile_format_open_ffmpg, MMFileFormatIsValidMatroska},        /* MATROSAK */
88         {mmfile_format_open_ffmpg, MMFileFormatIsValidMP4},                     /* MP4 */
89         {mmfile_format_open_ffmpg, MMFileFormatIsValidOGG},                     /* OGG */
90         {NULL, NULL},                                                                                           /* NUT */
91         {mmfile_format_open_ffmpg, MMFileFormatIsValidMP4},                     /* QT */
92         {mmfile_format_open_ffmpg, MMFileFormatIsValidREAL},            /* REAL */
93         {mmfile_format_open_amr,   MMFileFormatIsValidAMR},                     /* AMR */
94         {mmfile_format_open_aac,   MMFileFormatIsValidAAC},                     /* AAC */
95         {mmfile_format_open_mp3,   MMFileFormatIsValidMP3},                     /* MP3 */
96         {mmfile_format_open_ffmpg, MMFileFormatIsValidAIFF},                    /* AIFF */
97         {NULL, NULL},                                                                                           /* AU */
98         {mmfile_format_open_wav,   MMFileFormatIsValidWAV},                     /* WAV */
99         {mmfile_format_open_mid,   MMFileFormatIsValidMID},                     /* MID */
100         {mmfile_format_open_mmf,   MMFileFormatIsValidMMF},                     /* MMF */
101         {mmfile_format_open_ffmpg, MMFileFormatIsValidAVI},                     /* DIVX */
102         {mmfile_format_open_ffmpg, MMFileFormatIsValidFLV},                     /* FLV */
103         {NULL, NULL},                                                                                           /* VOB */
104         {mmfile_format_open_imy,   MMFileFormatIsValidIMY},                     /* IMY */
105         {mmfile_format_open_ffmpg, MMFileFormatIsValidWMA},                     /* WMA */
106         {mmfile_format_open_ffmpg, MMFileFormatIsValidWMV},                     /* WMV */
107         {NULL, NULL},                                                                                           /* JPG */
108         {mmfile_format_open_ffmpg, MMFileFormatIsValidFLAC},            /* FLAC */
109         {mmfile_format_open_ffmpg, MMFileFormatIsValidMPEGTS},          /* MPEG-TS */
110         {mmfile_format_open_ffmpg, MMFileFormatIsValidMPEGPS},          /* MPEG-PS */
111         {mmfile_format_open_ffmpg, MMFileFormatIsValidMPEGVIDEO},       /* MPEG 1 VIDEO */
112         {mmfile_format_open_ffmpg, MMFileFormatIsValidMPEGAUDIO},       /* MPEG 1 AUDIO */
113         {mmfile_format_open_ffmpg, MMFileFormatIsValidAPE},                     /* APE */
114         {NULL, NULL}
115 };
116
117 static int _CleanupFrameContext(MMFileFormatContext *formatContext, bool clean_all)
118 {
119         if (formatContext) {
120
121                 if (formatContext->ReadStream)  formatContext->ReadStream       = NULL;
122                 if (formatContext->ReadFrame)           formatContext->ReadFrame        = NULL;
123                 if (formatContext->ReadTag)             formatContext->ReadTag          = NULL;
124                 if (formatContext->Close)                       formatContext->Close                    = NULL;
125
126                 if (formatContext->uriFileName)         mmfile_free(formatContext->uriFileName);
127                 if (formatContext->title)                               mmfile_free(formatContext->title);
128                 if (formatContext->artist)                              mmfile_free(formatContext->artist);
129                 if (formatContext->author)                      mmfile_free(formatContext->author);
130                 if (formatContext->composer)                    mmfile_free(formatContext->composer);
131                 if (formatContext->album)                               mmfile_free(formatContext->album);
132                 if (formatContext->album_artist)                mmfile_free(formatContext->album_artist);
133                 if (formatContext->copyright)                   mmfile_free(formatContext->copyright);
134                 if (formatContext->description)                 mmfile_free(formatContext->description);
135                 if (formatContext->comment)                     mmfile_free(formatContext->comment);
136                 if (formatContext->genre)                               mmfile_free(formatContext->genre);
137                 if (formatContext->classification)              mmfile_free(formatContext->classification);
138                 if (formatContext->year)                                mmfile_free(formatContext->year);
139                 if (formatContext->recDate)                     mmfile_free(formatContext->recDate);
140                 if (formatContext->tagTrackNum)         mmfile_free(formatContext->tagTrackNum);
141                 if (formatContext->rating)                              mmfile_free(formatContext->rating);
142                 if (formatContext->artworkMime)         mmfile_free(formatContext->artworkMime);
143                 if (formatContext->artwork)                     mmfile_free(formatContext->artwork);
144                 if (formatContext->conductor)                   mmfile_free(formatContext->conductor);
145                 if (formatContext->unsyncLyrics)                mmfile_free(formatContext->unsyncLyrics);
146                 if (formatContext->rotate)                              mmfile_free(formatContext->rotate);
147                 if (formatContext->stereoMode)                  mmfile_free(formatContext->stereoMode);
148                 if (formatContext->stitchingSoftware)   mmfile_free(formatContext->stitchingSoftware);
149                 if (formatContext->projectionType)              mmfile_free(formatContext->projectionType);
150                 if (formatContext->metadataSourceV2)    mmfile_free(formatContext->metadataSourceV2);
151
152                 if (clean_all)  /*syncLyrics has to be freed in mm_file_destroy_tag_attrs() except abnormal status */
153                         if (formatContext->syncLyrics)                  mm_file_free_synclyrics_list(formatContext->syncLyrics);
154
155                 if (formatContext->privateFormatData)   mmfile_free(formatContext->privateFormatData);
156                 if (formatContext->privateCodecData)    mmfile_free(formatContext->privateCodecData);
157
158                 if (formatContext->nbStreams > 0) {
159                         int i = 0;
160
161                         /*formatContext->streams[0] is video, formatContext->streams[1] is audio.*/
162                         if (formatContext->streams[0]) mmfile_free(formatContext->streams[0]);
163                         if (formatContext->streams[1]) mmfile_free(formatContext->streams[1]);
164
165                         for (i = 2; (i < formatContext->nbStreams) && (i < MAXSTREAMS); i++) {
166                                 if (formatContext->streams[i]) mmfile_free(formatContext->streams[i]);
167                         }
168                 }
169
170                 if (formatContext->thumbNail) {
171                         if (formatContext->thumbNail->frameData)
172                                 mmfile_free(formatContext->thumbNail->frameData);
173
174                         if (formatContext->thumbNail->configData)
175                                 mmfile_free(formatContext->thumbNail->configData);
176
177                         mmfile_free(formatContext->thumbNail);
178                 }
179
180                 formatContext->videoTotalTrackNum = 0;
181                 formatContext->audioTotalTrackNum = 0;
182                 formatContext->nbStreams = 0;
183         }
184
185         return MMFILE_FORMAT_SUCCESS;
186 }
187
188 int fileExtToFormatType(unsigned long long fileExt)
189 {
190         switch (fileExt) {
191         case MMFILE_EXT_MP4:
192         case MMFILE_EXT_MPEG4:
193         case MMFILE_EXT_M4A:
194         case MMFILE_EXT_MPG:
195         case MMFILE_EXT_MPG4:
196         case MMFILE_EXT_M4V:
197         case MMFILE_EXT_TTS:
198         case MMFILE_EXT_TRP:
199         case MMFILE_EXT_3M:
200         case MMFILE_EXT_26L:
201         case MMFILE_EXT_264:
202                 return MM_FILE_FORMAT_MP4;
203
204         case MMFILE_EXT_3GP:
205                 return MM_FILE_FORMAT_3GP;
206
207         case MMFILE_EXT_AMR:
208         case MMFILE_EXT_AWB:
209                 return MM_FILE_FORMAT_AMR;
210
211         case MMFILE_EXT_WAV:
212                 return MM_FILE_FORMAT_WAV;
213
214         case MMFILE_EXT_MID:
215         case MMFILE_EXT_MIDI:
216         case MMFILE_EXT_SPM:
217                 return MM_FILE_FORMAT_MID;
218
219         case MMFILE_EXT_MP3:
220                 return MM_FILE_FORMAT_MP3;
221
222         case MMFILE_EXT_AAC:
223                 return MM_FILE_FORMAT_AAC;
224
225         case MMFILE_EXT_XMF:
226         case MMFILE_EXT_MXMF:
227                 return MM_FILE_FORMAT_MID;
228
229         case MMFILE_EXT_MMF:
230         case MMFILE_EXT_MA2:
231                 return MM_FILE_FORMAT_MMF;
232
233         case MMFILE_EXT_IMY:
234                 return MM_FILE_FORMAT_IMELODY;
235
236         case MMFILE_EXT_AVI:
237                 return MM_FILE_FORMAT_AVI;
238
239         case MMFILE_EXT_DIVX:
240                 return MM_FILE_FORMAT_DIVX;
241
242         case MMFILE_EXT_ASF:
243         case MMFILE_EXT_ASX:
244                 return MM_FILE_FORMAT_ASF;
245
246         case MMFILE_EXT_WMA:
247                 return MM_FILE_FORMAT_WMA;
248
249         case MMFILE_EXT_WMV:
250                 return MM_FILE_FORMAT_WMV;
251
252         case MMFILE_EXT_OGG:
253                 return MM_FILE_FORMAT_OGG;
254
255         case MMFILE_EXT_MKV:
256         case MMFILE_EXT_MKA:
257         case MMFILE_EXT_WEBM:
258                 return MM_FILE_FORMAT_MATROSKA;
259
260         case MMFILE_EXT_MOV:
261                 return MM_FILE_FORMAT_QT;
262
263         case MMFILE_EXT_FLAC:
264                 return MM_FILE_FORMAT_FLAC;
265
266         case MMFILE_EXT_FLV:
267                 return MM_FILE_FORMAT_FLV;
268
269         case MMFILE_EXT_RM:
270         case MMFILE_EXT_RMVB:
271                 return MM_FILE_FORMAT_REAL;
272
273         case MMFILE_EXT_M2TS:
274         case MMFILE_EXT_MTS:
275         case MMFILE_EXT_TP:
276         case MMFILE_EXT_TS:
277                 return MM_FILE_FORMAT_M2TS;
278
279         case MMFILE_EXT_MPEG:
280                 return MM_FILE_FORMAT_M2PS;
281
282         case MMFILE_EXT_AIF:
283         case MMFILE_EXT_AIFF:
284                 return MM_FILE_FORMAT_AIFF;
285
286         case MMFILE_EXT_APE:
287                 return MM_FILE_FORMAT_APE;
288         default:
289                 return MM_FILE_FORMAT_NUM;
290         }
291 }
292
293 static int
294 _PreprocessFile(MMFileSourceType *fileSrc, char **urifilename, int *formatEnum)
295 {
296         const char      *fileName = NULL;
297         int                     filename_len = 0;
298         int                     index = 0, skip_index = 0;
299         int ret = 0;
300         MMFileIOHandle *fp = NULL;
301
302         if (fileSrc->type == MM_FILE_SRC_TYPE_FILE) {
303                 unsigned long long fileExt = 0;
304 #ifdef __MMFILE_MMAP_MODE__
305                 const char *uriStr = MMFILE_MMAP_URI;
306 #else
307                 const char *uriStr = MMFILE_FILE_URI;
308 #endif
309                 int uriLen = strlen(uriStr);
310
311                 fileName = (const char *)(fileSrc->file.path);
312                 filename_len = strlen(fileName);
313
314                 int pos = filename_len;
315
316                 *urifilename = mmfile_malloc(uriLen + filename_len + 1);
317                 if (!*urifilename) {
318                         debug_error(DEBUG, "error: mmfile_malloc uriname\n");
319                         goto FILE_FORMAT_FAIL;
320                 }
321
322                 memset(*urifilename, 0x00, uriLen + filename_len + 1);
323                 SAFE_STRLCPY(*urifilename, uriStr, uriLen + filename_len + 1);
324                 SAFE_STRLCAT(*urifilename, fileName, uriLen + filename_len + 1);
325
326                 /**
327                  * Get file extension from file's name
328                  */
329                 while (pos > 0) {
330                         pos--;
331                         if (fileName[pos] == '.')
332                                 break;
333                         fileExt |= (fileName[pos] >= 'A' && fileName[pos] <= 'Z' ? fileName[pos] + 0x20 : fileName[pos]) << (filename_len - pos - 1) * 8;
334                 }
335
336                 skip_index = fileExtToFormatType(fileExt);
337
338                 ret = mmfile_open(&fp, *urifilename, MMFILE_RDONLY);
339
340                 if (ret == MMFILE_IO_FAILED) {
341                         debug_error(DEBUG, "error: mmfile_open\n");
342                         goto FILE_FORMAT_FAIL;
343                 }
344         } else if (fileSrc->type == MM_FILE_SRC_TYPE_MEMORY) {
345                 char tempURIBuffer[MMFILE_URI_MAX_LEN] = {0, };
346
347                 snprintf(tempURIBuffer, MMFILE_URI_MAX_LEN, "%s%lu:%u", MMFILE_MEM_URI, (unsigned long)fileSrc->memory.ptr, fileSrc->memory.size);
348                 *urifilename = mmfile_strdup(tempURIBuffer);
349                 if (!*urifilename) {
350                         debug_error(DEBUG, "error: uri is NULL\n");
351                         goto FILE_FORMAT_FAIL;
352                 }
353
354                 ret = mmfile_open(&fp, *urifilename, MMFILE_RDONLY);
355
356                 if (ret == MMFILE_IO_FAILED) {
357                         debug_error(DEBUG, "error: mmfile_open\n");
358                         goto FILE_FORMAT_FAIL;
359                 }
360
361                 debug_msg(RELEASE, "uri: %s\n", *urifilename);
362
363                 skip_index = fileSrc->memory.format;
364         } else {
365                 debug_error(DEBUG, "error: invaild input type[memory|file]\n");
366                 goto FILE_FORMAT_FAIL;
367         }
368
369         if (MMFileFunc[skip_index].Valid != NULL && MMFileFunc[skip_index].Valid(fp, NULL, 5)) {        // 3rd argument only mp3
370                 *formatEnum = skip_index;
371                 goto FILE_FORMAT_SUCCESS;
372         } else {
373                 if (skip_index == MM_FILE_FORMAT_M2PS) {
374                         if (MMFileFunc[MM_FILE_FORMAT_M1VIDEO].Valid(fp, NULL, 5)) {
375                                 *formatEnum = MM_FILE_FORMAT_M1VIDEO;
376                                 goto FILE_FORMAT_SUCCESS;
377                         }
378                 }
379                 goto PROBE_PROPER_FILE_TYPE;
380         }
381
382 PROBE_PROPER_FILE_TYPE:
383         for (index = 0; index < MM_FILE_FORMAT_NUM; index++) {
384                 if (index == skip_index)
385                         continue;
386
387                 debug_msg(RELEASE, "search index = [%d]\n", index);
388
389                 switch (index) {
390                 case MM_FILE_FORMAT_QT:
391                 case MM_FILE_FORMAT_3GP:
392                 case MM_FILE_FORMAT_MP4:
393                         *formatEnum = (skip_index == MM_FILE_FORMAT_QT || skip_index == MM_FILE_FORMAT_3GP || skip_index == MM_FILE_FORMAT_MP4) ? MM_FILE_FORMAT_NUM : MM_FILE_FORMAT_3GP;
394                         break;
395
396                 case MM_FILE_FORMAT_ASF:
397                 case MM_FILE_FORMAT_WMA:
398                 case MM_FILE_FORMAT_WMV:
399                         *formatEnum = (skip_index == MM_FILE_FORMAT_ASF || skip_index == MM_FILE_FORMAT_WMA || skip_index == MM_FILE_FORMAT_WMV) ? MM_FILE_FORMAT_NUM : MM_FILE_FORMAT_ASF;
400                         break;
401
402                 case MM_FILE_FORMAT_DIVX:
403                 case MM_FILE_FORMAT_AVI:
404                         *formatEnum = (skip_index == MM_FILE_FORMAT_DIVX || skip_index == MM_FILE_FORMAT_AVI) ? MM_FILE_FORMAT_NUM : MM_FILE_FORMAT_AVI;
405                         break;
406
407                 /* not supported file */
408                 case MM_FILE_FORMAT_NUT:
409                 case MM_FILE_FORMAT_AU:
410                 case MM_FILE_FORMAT_VOB:
411                 case MM_FILE_FORMAT_JPG:
412                         *formatEnum = MM_FILE_FORMAT_NUM;
413                         break;
414
415                 default:
416                         *formatEnum = index;
417                         //debug_error(RELEASE, "error: invaild format enum[%d]\n", index);
418                         break;
419                 }
420
421                 if (MMFileFunc[*formatEnum].Valid != NULL && MMFileFunc[*formatEnum].Valid(fp, NULL, 50)) {
422                         if (fileSrc->type == MM_FILE_SRC_TYPE_MEMORY) fileSrc->memory.format = *formatEnum;
423                         goto FILE_FORMAT_SUCCESS;
424                 }
425         }
426
427 FILE_FORMAT_FAIL:
428         if (index == MM_FILE_FORMAT_NUM)
429                 debug_error(DEBUG, "Can't probe file type\n");
430
431         *formatEnum = -1;
432
433         if (fp)
434                 mmfile_close(fp);
435
436         return MMFILE_FORMAT_FAIL;
437
438
439 FILE_FORMAT_SUCCESS:
440         if (fp)
441                 mmfile_close(fp);
442
443         return MMFILE_FORMAT_SUCCESS;
444 }
445
446 static int _mmfile_format_close(MMFileFormatContext *formatContext, bool clean_all)
447 {
448         if (NULL == formatContext) {
449                 debug_error(DEBUG, "error: invalid params\n");
450                 return MMFILE_FORMAT_FAIL;
451         }
452
453         if (formatContext->Close) {
454                 formatContext->Close(formatContext);
455                 formatContext->Close = NULL;
456         }
457
458         _CleanupFrameContext(formatContext, clean_all);
459
460         if (formatContext)
461                 mmfile_free(formatContext);
462
463         return MMFILE_FORMAT_SUCCESS;
464 }
465
466
467 EXPORT_API
468 int mmfile_format_open(MMFileFormatContext **formatContext, MMFileSourceType *fileSrc)
469 {
470         int index = 0;
471         int ret = 0;
472         MMFileFormatContext *formatObject = NULL;
473
474         if (NULL == fileSrc) {
475                 debug_error(DEBUG, "error: invalid params\n");
476                 return MMFILE_FORMAT_FAIL;
477         }
478
479         /* create formatContext object */
480         formatObject = mmfile_malloc(sizeof(MMFileFormatContext));
481         if (NULL == formatObject) {
482                 debug_error(DEBUG, "error: mmfile_malloc fail for formatObject\n");
483                 *formatContext = NULL;
484                 return MMFILE_FORMAT_FAIL;
485         }
486
487         memset(formatObject, 0x00, sizeof(MMFileFormatContext));
488
489         mmfile_register_io_all();
490
491         /* parsing file extension */
492         formatObject->filesrc = fileSrc;
493
494         formatObject->pre_checked = 0;  /*not yet format checked.*/
495
496         /**
497          * Format detect and validation check.
498          */
499         ret = _PreprocessFile(fileSrc, &formatObject->uriFileName,  &formatObject->formatType);
500         if (MMFILE_FORMAT_SUCCESS != ret) {
501                 debug_error(DEBUG, "error: _PreprocessFile fail\n");
502                 ret = MMFILE_FORMAT_FAIL;
503                 goto exception;
504         }
505
506         formatObject->pre_checked = 1;  /*already file format checked.*/
507
508         /**
509          * Open format function.
510          */
511         if (NULL == MMFileFunc[formatObject->formatType].Open) {
512                 debug_error(DEBUG, "error: Not implemented \n");
513                 ret = MMFILE_FORMAT_FAIL;
514                 goto find_valid_handler;
515         }
516
517         ret = MMFileFunc[formatObject->formatType].Open(formatObject);
518         if (MMFILE_FORMAT_FAIL == ret) {
519                 debug_error(DEBUG, "error: Try other formats\n");
520                 ret = MMFILE_FORMAT_FAIL;
521 /*              goto find_valid_handler; */
522                 goto exception;
523         }
524
525         *formatContext = formatObject;
526         return MMFILE_FORMAT_SUCCESS;
527
528 find_valid_handler:
529         formatObject->pre_checked = 0;  /*do check file format*/
530
531         for (index = 0; index < MM_FILE_FORMAT_NUM + 1; index++) {
532                 if (NULL == MMFileFunc[index].Open) {
533                         debug_error(DEBUG, "error: Not implemented \n");
534                         ret = MMFILE_FORMAT_FAIL;
535                         continue;
536                 }
537
538                 if (formatObject->formatType == index)
539                         continue;
540
541                 ret = MMFileFunc[index].Open(formatObject);
542                 if (MMFILE_FORMAT_FAIL == ret) {
543 /*                      _CleanupFrameContext(formatObject, true); */
544                         continue;
545                 }
546
547                 break;
548         }
549
550         formatObject->formatType = index;
551
552         if (index == MM_FILE_FORMAT_NUM + 1 && MMFILE_FORMAT_FAIL == ret) {
553                 debug_error(DEBUG, "can't find file format handler\n");
554                 _CleanupFrameContext(formatObject, true);
555                 ret = MMFILE_FORMAT_FAIL;
556                 goto exception;
557         }
558
559         formatObject->formatType = index;
560         *formatContext = formatObject;
561
562         return MMFILE_FORMAT_SUCCESS;
563
564 exception:
565         _mmfile_format_close(formatObject, true);
566         *formatContext = NULL;
567
568         return ret;
569 }
570
571 EXPORT_API
572 int mmfile_format_read_stream(MMFileFormatContext *formatContext)
573 {
574         if (NULL == formatContext || NULL == formatContext->ReadStream) {
575                 debug_error(DEBUG, "error: invalid params\n");
576                 return MMFILE_FORMAT_FAIL;
577         }
578
579         return formatContext->ReadStream(formatContext);
580 }
581
582 EXPORT_API
583 int mmfile_format_read_frame(MMFileFormatContext *formatContext, unsigned int timestamp, MMFileFormatFrame *frame)
584 {
585         if (NULL == formatContext || NULL == frame || NULL == formatContext->ReadFrame) {
586                 debug_error(DEBUG, "error: invalid params\n");
587                 return MMFILE_FORMAT_FAIL;
588         }
589
590         return formatContext->ReadFrame(formatContext, timestamp, frame);
591 }
592
593 EXPORT_API
594 int mmfile_format_read_tag(MMFileFormatContext *formatContext)
595 {
596         if (NULL == formatContext || NULL == formatContext->ReadTag) {
597                 debug_error(DEBUG, "error: invalid params\n");
598                 return MMFILE_FORMAT_FAIL;
599         }
600
601         return formatContext->ReadTag(formatContext);
602 }
603
604
605 EXPORT_API
606 int mmfile_format_close(MMFileFormatContext *formatContext)
607 {
608         return _mmfile_format_close(formatContext, false);
609 }