4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Haejeong Kim <backto.kim@samsung.com>
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
25 #include "mm_file_debug.h"
26 #include "mm_file_format_private.h"
27 #include "mm_file_utils.h"
29 #define _MMF_FILE_FILEEXT_MAX 128
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
80 int (*Open)(MMFileFormatContext *fileContext);
81 int (*Valid)(MMFileIOHandle *pFileIO, const char *mmfileuri, int mp3FrameCnt);
82 } MMFileFunc[MM_FILE_FORMAT_NUM + 1] = {
83 {mmfile_format_open_ffmpg, MMFileFormatIsValidMP4}, /* 3GP */
84 {mmfile_format_open_ffmpg, MMFileFormatIsValidASF}, /* ASF */
85 {mmfile_format_open_ffmpg, MMFileFormatIsValidAVI}, /* AVI */
86 {mmfile_format_open_ffmpg, MMFileFormatIsValidMatroska}, /* MATROSAK */
87 {mmfile_format_open_ffmpg, MMFileFormatIsValidMP4}, /* MP4 */
88 {mmfile_format_open_ffmpg, MMFileFormatIsValidOGG}, /* OGG */
89 {NULL, NULL}, /* NUT */
90 {mmfile_format_open_ffmpg, MMFileFormatIsValidMP4}, /* QT */
91 {mmfile_format_open_ffmpg, MMFileFormatIsValidREAL}, /* REAL */
92 {mmfile_format_open_amr, MMFileFormatIsValidAMR}, /* AMR */
93 {mmfile_format_open_aac, MMFileFormatIsValidAAC}, /* AAC */
94 {mmfile_format_open_mp3, MMFileFormatIsValidMP3}, /* MP3 */
95 {mmfile_format_open_ffmpg, MMFileFormatIsValidAIFF}, /* AIFF */
96 {NULL, NULL}, /* AU */
97 {mmfile_format_open_wav, MMFileFormatIsValidWAV}, /* WAV */
98 {mmfile_format_open_mid, MMFileFormatIsValidMID}, /* MID */
99 {mmfile_format_open_mmf, MMFileFormatIsValidMMF}, /* MMF */
100 {mmfile_format_open_ffmpg, MMFileFormatIsValidAVI}, /* DIVX */
101 {mmfile_format_open_ffmpg, MMFileFormatIsValidFLV}, /* FLV */
102 {NULL, NULL}, /* VOB */
103 {mmfile_format_open_imy, MMFileFormatIsValidIMY}, /* IMY */
104 {mmfile_format_open_ffmpg, MMFileFormatIsValidWMA}, /* WMA */
105 {mmfile_format_open_ffmpg, MMFileFormatIsValidWMV}, /* WMV */
106 {NULL, NULL}, /* JPG */
107 {mmfile_format_open_ffmpg, MMFileFormatIsValidFLAC}, /* FLAC */
108 {mmfile_format_open_ffmpg, MMFileFormatIsValidMPEGTS}, /* MPEG-TS */
109 {mmfile_format_open_ffmpg, MMFileFormatIsValidMPEGPS}, /* MPEG-PS */
110 {mmfile_format_open_ffmpg, MMFileFormatIsValidMPEGVIDEO}, /* MPEG 1 VIDEO */
111 {mmfile_format_open_ffmpg, MMFileFormatIsValidMPEGAUDIO}, /* MPEG 1 AUDIO */
115 static int _CleanupFrameContext(MMFileFormatContext *formatContext, bool clean_all)
119 if (formatContext->ReadStream) formatContext->ReadStream = NULL;
120 if (formatContext->ReadFrame) formatContext->ReadFrame = NULL;
121 if (formatContext->ReadTag) formatContext->ReadTag = NULL;
122 if (formatContext->Close) formatContext->Close = NULL;
124 if (formatContext->uriFileName) mmfile_free(formatContext->uriFileName);
125 if (formatContext->title) mmfile_free(formatContext->title);
126 if (formatContext->artist) mmfile_free(formatContext->artist);
127 if (formatContext->author) mmfile_free(formatContext->author);
128 if (formatContext->composer) mmfile_free(formatContext->composer);
129 if (formatContext->album) mmfile_free(formatContext->album);
130 if (formatContext->album_artist) mmfile_free(formatContext->album_artist);
131 if (formatContext->copyright) mmfile_free(formatContext->copyright);
132 if (formatContext->description) mmfile_free(formatContext->description);
133 if (formatContext->comment) mmfile_free(formatContext->comment);
134 if (formatContext->genre) mmfile_free(formatContext->genre);
135 if (formatContext->classification) mmfile_free(formatContext->classification);
136 if (formatContext->year) mmfile_free(formatContext->year);
137 if (formatContext->recDate) mmfile_free(formatContext->recDate);
138 if (formatContext->tagTrackNum) mmfile_free(formatContext->tagTrackNum);
139 if (formatContext->rating) mmfile_free(formatContext->rating);
140 if (formatContext->artworkMime) mmfile_free(formatContext->artworkMime);
141 if (formatContext->artwork) mmfile_free(formatContext->artwork);
142 if (formatContext->conductor) mmfile_free(formatContext->conductor);
143 if (formatContext->unsyncLyrics) mmfile_free(formatContext->unsyncLyrics);
144 if (formatContext->rotate) mmfile_free(formatContext->rotate);
145 if (formatContext->stereoMode) mmfile_free(formatContext->stereoMode);
146 if (formatContext->stitchingSoftware) mmfile_free(formatContext->stitchingSoftware);
147 if (formatContext->projectionType) mmfile_free(formatContext->projectionType);
148 if (formatContext->metadataSourceV2) mmfile_free(formatContext->metadataSourceV2);
150 if (clean_all) /*syncLyrics has to be freed in mm_file_destroy_tag_attrs() except abnormal status */
151 if (formatContext->syncLyrics) mm_file_free_synclyrics_list(formatContext->syncLyrics);
153 if (formatContext->privateFormatData) mmfile_free(formatContext->privateFormatData);
154 if (formatContext->privateCodecData) mmfile_free(formatContext->privateCodecData);
156 if (formatContext->nbStreams > 0) {
159 /*formatContext->streams[0] is video, formatContext->streams[1] is audio.*/
160 if (formatContext->streams[0]) mmfile_free(formatContext->streams[0]);
161 if (formatContext->streams[1]) mmfile_free(formatContext->streams[1]);
163 for (i = 2; (i < formatContext->nbStreams) && (i < MAXSTREAMS); i++) {
164 if (formatContext->streams[i]) mmfile_free(formatContext->streams[i]);
168 if (formatContext->thumbNail) {
169 if (formatContext->thumbNail->frameData)
170 mmfile_free(formatContext->thumbNail->frameData);
172 if (formatContext->thumbNail->configData)
173 mmfile_free(formatContext->thumbNail->configData);
175 mmfile_free(formatContext->thumbNail);
178 formatContext->videoTotalTrackNum = 0;
179 formatContext->audioTotalTrackNum = 0;
180 formatContext->nbStreams = 0;
183 return MMFILE_FORMAT_SUCCESS;
186 int fileExtToFormatType(unsigned long long fileExt)
190 case MMFILE_EXT_MPEG4:
193 case MMFILE_EXT_MPG4:
200 return MM_FILE_FORMAT_MP4;
203 return MM_FILE_FORMAT_3GP;
207 return MM_FILE_FORMAT_AMR;
210 return MM_FILE_FORMAT_WAV;
213 case MMFILE_EXT_MIDI:
215 return MM_FILE_FORMAT_MID;
218 return MM_FILE_FORMAT_MP3;
221 return MM_FILE_FORMAT_AAC;
224 case MMFILE_EXT_MXMF:
225 return MM_FILE_FORMAT_MID;
229 return MM_FILE_FORMAT_MMF;
232 return MM_FILE_FORMAT_IMELODY;
235 return MM_FILE_FORMAT_AVI;
237 case MMFILE_EXT_DIVX:
238 return MM_FILE_FORMAT_DIVX;
242 return MM_FILE_FORMAT_ASF;
245 return MM_FILE_FORMAT_WMA;
248 return MM_FILE_FORMAT_WMV;
251 return MM_FILE_FORMAT_OGG;
255 case MMFILE_EXT_WEBM:
256 return MM_FILE_FORMAT_MATROSKA;
259 return MM_FILE_FORMAT_QT;
261 case MMFILE_EXT_FLAC:
262 return MM_FILE_FORMAT_FLAC;
265 return MM_FILE_FORMAT_FLV;
268 case MMFILE_EXT_RMVB:
269 return MM_FILE_FORMAT_REAL;
271 case MMFILE_EXT_M2TS:
275 return MM_FILE_FORMAT_M2TS;
277 case MMFILE_EXT_MPEG:
278 return MM_FILE_FORMAT_M2PS;
281 case MMFILE_EXT_AIFF:
282 return MM_FILE_FORMAT_AIFF;
285 return MM_FILE_FORMAT_NUM;
290 _PreprocessFile(MMFileSourceType *fileSrc, char **urifilename, int *formatEnum)
292 const char *fileName = NULL;
293 int filename_len = 0;
294 int index = 0, skip_index = 0;
296 MMFileIOHandle *fp = NULL;
298 if (fileSrc->type == MM_FILE_SRC_TYPE_FILE) {
299 unsigned long long fileExt = 0;
300 #ifdef __MMFILE_MMAP_MODE__
301 const char *uriStr = MMFILE_MMAP_URI;
303 const char *uriStr = MMFILE_FILE_URI;
305 int uriLen = strlen(uriStr);
307 fileName = (const char *)(fileSrc->file.path);
308 filename_len = strlen(fileName);
310 int pos = filename_len;
312 *urifilename = mmfile_malloc(uriLen + filename_len + 1);
314 debug_error(DEBUG, "error: mmfile_malloc uriname\n");
315 goto FILE_FORMAT_FAIL;
318 memset(*urifilename, 0x00, uriLen + filename_len + 1);
319 SAFE_STRLCPY(*urifilename, uriStr, uriLen + filename_len + 1);
320 SAFE_STRLCAT(*urifilename, fileName, uriLen + filename_len + 1);
323 * Get file extension from file's name
327 if (fileName[pos] == '.')
329 fileExt |= (fileName[pos] >= 'A' && fileName[pos] <= 'Z' ? fileName[pos] + 0x20 : fileName[pos]) << (filename_len - pos - 1) * 8;
332 skip_index = fileExtToFormatType(fileExt);
334 ret = mmfile_open(&fp, *urifilename, MMFILE_RDONLY);
336 if (ret == MMFILE_IO_FAILED) {
337 debug_error(DEBUG, "error: mmfile_open\n");
338 goto FILE_FORMAT_FAIL;
340 } else if (fileSrc->type == MM_FILE_SRC_TYPE_MEMORY) {
341 char tempURIBuffer[MMFILE_URI_MAX_LEN] = {0, };
343 snprintf(tempURIBuffer, MMFILE_URI_MAX_LEN, "%s%lu:%u", MMFILE_MEM_URI, (unsigned long)fileSrc->memory.ptr, fileSrc->memory.size);
344 *urifilename = mmfile_strdup(tempURIBuffer);
346 debug_error(DEBUG, "error: uri is NULL\n");
347 goto FILE_FORMAT_FAIL;
350 ret = mmfile_open(&fp, *urifilename, MMFILE_RDONLY);
352 if (ret == MMFILE_IO_FAILED) {
353 debug_error(DEBUG, "error: mmfile_open\n");
354 goto FILE_FORMAT_FAIL;
357 debug_msg(RELEASE, "uri: %s\n", *urifilename);
359 skip_index = fileSrc->memory.format;
361 debug_error(DEBUG, "error: invaild input type[memory|file]\n");
362 goto FILE_FORMAT_FAIL;
365 if (MMFileFunc[skip_index].Valid != NULL && MMFileFunc[skip_index].Valid(fp, NULL, 5)) { // 3rd argument only mp3
366 *formatEnum = skip_index;
367 goto FILE_FORMAT_SUCCESS;
369 if (skip_index == MM_FILE_FORMAT_M2PS) {
370 if (MMFileFunc[MM_FILE_FORMAT_M1VIDEO].Valid(fp, NULL, 5)) {
371 *formatEnum = MM_FILE_FORMAT_M1VIDEO;
372 goto FILE_FORMAT_SUCCESS;
375 goto PROBE_PROPER_FILE_TYPE;
378 PROBE_PROPER_FILE_TYPE:
379 for (index = 0; index < MM_FILE_FORMAT_NUM; index++) {
380 if (index == skip_index)
383 debug_msg(RELEASE, "search index = [%d]\n", index);
386 case MM_FILE_FORMAT_QT:
387 case MM_FILE_FORMAT_3GP:
388 case MM_FILE_FORMAT_MP4:
389 *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;
392 case MM_FILE_FORMAT_ASF:
393 case MM_FILE_FORMAT_WMA:
394 case MM_FILE_FORMAT_WMV:
395 *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;
398 case MM_FILE_FORMAT_DIVX:
399 case MM_FILE_FORMAT_AVI:
400 *formatEnum = (skip_index == MM_FILE_FORMAT_DIVX || skip_index == MM_FILE_FORMAT_AVI) ? MM_FILE_FORMAT_NUM : MM_FILE_FORMAT_AVI;
403 /* not supported file */
404 case MM_FILE_FORMAT_NUT:
405 case MM_FILE_FORMAT_AU:
406 case MM_FILE_FORMAT_VOB:
407 case MM_FILE_FORMAT_JPG:
408 *formatEnum = MM_FILE_FORMAT_NUM;
413 //debug_error(RELEASE, "error: invaild format enum[%d]\n", index);
417 if (MMFileFunc[*formatEnum].Valid != NULL && MMFileFunc[*formatEnum].Valid(fp, NULL, 50)) {
418 if (fileSrc->type == MM_FILE_SRC_TYPE_MEMORY) fileSrc->memory.format = *formatEnum;
419 goto FILE_FORMAT_SUCCESS;
424 if (index == MM_FILE_FORMAT_NUM)
425 debug_error(DEBUG, "Can't probe file type\n");
432 return MMFILE_FORMAT_FAIL;
439 return MMFILE_FORMAT_SUCCESS;
442 static int _mmfile_format_close(MMFileFormatContext *formatContext, bool clean_all)
444 if (NULL == formatContext) {
445 debug_error(DEBUG, "error: invalid params\n");
446 return MMFILE_FORMAT_FAIL;
449 if (formatContext->Close) {
450 formatContext->Close(formatContext);
451 formatContext->Close = NULL;
454 _CleanupFrameContext(formatContext, clean_all);
457 mmfile_free(formatContext);
459 return MMFILE_FORMAT_SUCCESS;
464 int mmfile_format_open(MMFileFormatContext **formatContext, MMFileSourceType *fileSrc)
468 MMFileFormatContext *formatObject = NULL;
470 if (NULL == fileSrc) {
471 debug_error(DEBUG, "error: invalid params\n");
472 return MMFILE_FORMAT_FAIL;
475 /* create formatContext object */
476 formatObject = mmfile_malloc(sizeof(MMFileFormatContext));
477 if (NULL == formatObject) {
478 debug_error(DEBUG, "error: mmfile_malloc fail for formatObject\n");
479 *formatContext = NULL;
480 return MMFILE_FORMAT_FAIL;
483 memset(formatObject, 0x00, sizeof(MMFileFormatContext));
485 mmfile_register_io_all();
487 /* parsing file extension */
488 formatObject->filesrc = fileSrc;
490 formatObject->pre_checked = 0; /*not yet format checked.*/
493 * Format detect and validation check.
495 ret = _PreprocessFile(fileSrc, &formatObject->uriFileName, &formatObject->formatType);
496 if (MMFILE_FORMAT_SUCCESS != ret) {
497 debug_error(DEBUG, "error: _PreprocessFile fail\n");
498 ret = MMFILE_FORMAT_FAIL;
502 formatObject->pre_checked = 1; /*already file format checked.*/
505 * Open format function.
507 if (NULL == MMFileFunc[formatObject->formatType].Open) {
508 debug_error(DEBUG, "error: Not implemented \n");
509 ret = MMFILE_FORMAT_FAIL;
510 goto find_valid_handler;
513 ret = MMFileFunc[formatObject->formatType].Open(formatObject);
514 if (MMFILE_FORMAT_FAIL == ret) {
515 debug_error(DEBUG, "error: Try other formats\n");
516 ret = MMFILE_FORMAT_FAIL;
517 /* goto find_valid_handler; */
521 *formatContext = formatObject;
522 return MMFILE_FORMAT_SUCCESS;
525 formatObject->pre_checked = 0; /*do check file format*/
527 for (index = 0; index < MM_FILE_FORMAT_NUM + 1; index++) {
528 if (NULL == MMFileFunc[index].Open) {
529 debug_error(DEBUG, "error: Not implemented \n");
530 ret = MMFILE_FORMAT_FAIL;
534 if (formatObject->formatType == index)
537 ret = MMFileFunc[index].Open(formatObject);
538 if (MMFILE_FORMAT_FAIL == ret) {
539 /* _CleanupFrameContext(formatObject, true); */
546 formatObject->formatType = index;
548 if (index == MM_FILE_FORMAT_NUM + 1 && MMFILE_FORMAT_FAIL == ret) {
549 debug_error(DEBUG, "can't find file format handler\n");
550 _CleanupFrameContext(formatObject, true);
551 ret = MMFILE_FORMAT_FAIL;
555 formatObject->formatType = index;
556 *formatContext = formatObject;
558 return MMFILE_FORMAT_SUCCESS;
561 _mmfile_format_close(formatObject, true);
562 *formatContext = NULL;
568 int mmfile_format_read_stream(MMFileFormatContext *formatContext)
570 if (NULL == formatContext || NULL == formatContext->ReadStream) {
571 debug_error(DEBUG, "error: invalid params\n");
572 return MMFILE_FORMAT_FAIL;
575 return formatContext->ReadStream(formatContext);
579 int mmfile_format_read_frame(MMFileFormatContext *formatContext, unsigned int timestamp, MMFileFormatFrame *frame)
581 if (NULL == formatContext || NULL == frame || NULL == formatContext->ReadFrame) {
582 debug_error(DEBUG, "error: invalid params\n");
583 return MMFILE_FORMAT_FAIL;
586 return formatContext->ReadFrame(formatContext, timestamp, frame);
590 int mmfile_format_read_tag(MMFileFormatContext *formatContext)
592 if (NULL == formatContext || NULL == formatContext->ReadTag) {
593 debug_error(DEBUG, "error: invalid params\n");
594 return MMFILE_FORMAT_FAIL;
597 return formatContext->ReadTag(formatContext);
602 int mmfile_format_close(MMFileFormatContext *formatContext)
604 return _mmfile_format_close(formatContext, false);