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
78 #define MMFILE_EXT_APE 0x617065
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 */
117 static int _CleanupFrameContext(MMFileFormatContext *formatContext, bool clean_all)
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;
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);
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);
155 if (formatContext->privateFormatData) mmfile_free(formatContext->privateFormatData);
156 if (formatContext->privateCodecData) mmfile_free(formatContext->privateCodecData);
158 if (formatContext->nbStreams > 0) {
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]);
165 for (i = 2; (i < formatContext->nbStreams) && (i < MAXSTREAMS); i++) {
166 if (formatContext->streams[i]) mmfile_free(formatContext->streams[i]);
170 if (formatContext->thumbNail) {
171 if (formatContext->thumbNail->frameData)
172 mmfile_free(formatContext->thumbNail->frameData);
174 if (formatContext->thumbNail->configData)
175 mmfile_free(formatContext->thumbNail->configData);
177 mmfile_free(formatContext->thumbNail);
180 formatContext->videoTotalTrackNum = 0;
181 formatContext->audioTotalTrackNum = 0;
182 formatContext->nbStreams = 0;
185 return MMFILE_FORMAT_SUCCESS;
188 int fileExtToFormatType(unsigned long long fileExt)
192 case MMFILE_EXT_MPEG4:
195 case MMFILE_EXT_MPG4:
202 return MM_FILE_FORMAT_MP4;
205 return MM_FILE_FORMAT_3GP;
209 return MM_FILE_FORMAT_AMR;
212 return MM_FILE_FORMAT_WAV;
215 case MMFILE_EXT_MIDI:
217 return MM_FILE_FORMAT_MID;
220 return MM_FILE_FORMAT_MP3;
223 return MM_FILE_FORMAT_AAC;
226 case MMFILE_EXT_MXMF:
227 return MM_FILE_FORMAT_MID;
231 return MM_FILE_FORMAT_MMF;
234 return MM_FILE_FORMAT_IMELODY;
237 return MM_FILE_FORMAT_AVI;
239 case MMFILE_EXT_DIVX:
240 return MM_FILE_FORMAT_DIVX;
244 return MM_FILE_FORMAT_ASF;
247 return MM_FILE_FORMAT_WMA;
250 return MM_FILE_FORMAT_WMV;
253 return MM_FILE_FORMAT_OGG;
257 case MMFILE_EXT_WEBM:
258 return MM_FILE_FORMAT_MATROSKA;
261 return MM_FILE_FORMAT_QT;
263 case MMFILE_EXT_FLAC:
264 return MM_FILE_FORMAT_FLAC;
267 return MM_FILE_FORMAT_FLV;
270 case MMFILE_EXT_RMVB:
271 return MM_FILE_FORMAT_REAL;
273 case MMFILE_EXT_M2TS:
277 return MM_FILE_FORMAT_M2TS;
279 case MMFILE_EXT_MPEG:
280 return MM_FILE_FORMAT_M2PS;
283 case MMFILE_EXT_AIFF:
284 return MM_FILE_FORMAT_AIFF;
287 return MM_FILE_FORMAT_APE;
289 return MM_FILE_FORMAT_NUM;
294 _PreprocessFile(MMFileSourceType *fileSrc, char **urifilename, int *formatEnum)
296 const char *fileName = NULL;
297 int filename_len = 0;
298 int index = 0, skip_index = 0;
300 MMFileIOHandle *fp = NULL;
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;
307 const char *uriStr = MMFILE_FILE_URI;
309 int uriLen = strlen(uriStr);
311 fileName = (const char *)(fileSrc->file.path);
312 filename_len = strlen(fileName);
314 int pos = filename_len;
316 *urifilename = mmfile_malloc(uriLen + filename_len + 1);
318 debug_error(DEBUG, "error: mmfile_malloc uriname\n");
319 goto FILE_FORMAT_FAIL;
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);
327 * Get file extension from file's name
331 if (fileName[pos] == '.')
333 fileExt |= (fileName[pos] >= 'A' && fileName[pos] <= 'Z' ? fileName[pos] + 0x20 : fileName[pos]) << (filename_len - pos - 1) * 8;
336 skip_index = fileExtToFormatType(fileExt);
338 ret = mmfile_open(&fp, *urifilename, MMFILE_RDONLY);
340 if (ret == MMFILE_IO_FAILED) {
341 debug_error(DEBUG, "error: mmfile_open\n");
342 goto FILE_FORMAT_FAIL;
344 } else if (fileSrc->type == MM_FILE_SRC_TYPE_MEMORY) {
345 char tempURIBuffer[MMFILE_URI_MAX_LEN] = {0, };
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);
350 debug_error(DEBUG, "error: uri is NULL\n");
351 goto FILE_FORMAT_FAIL;
354 ret = mmfile_open(&fp, *urifilename, MMFILE_RDONLY);
356 if (ret == MMFILE_IO_FAILED) {
357 debug_error(DEBUG, "error: mmfile_open\n");
358 goto FILE_FORMAT_FAIL;
361 debug_msg(RELEASE, "uri: %s\n", *urifilename);
363 skip_index = fileSrc->memory.format;
365 debug_error(DEBUG, "error: invaild input type[memory|file]\n");
366 goto FILE_FORMAT_FAIL;
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;
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;
379 goto PROBE_PROPER_FILE_TYPE;
382 PROBE_PROPER_FILE_TYPE:
383 for (index = 0; index < MM_FILE_FORMAT_NUM; index++) {
384 if (index == skip_index)
387 debug_msg(RELEASE, "search index = [%d]\n", 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;
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;
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;
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;
417 //debug_error(RELEASE, "error: invaild format enum[%d]\n", index);
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;
428 if (index == MM_FILE_FORMAT_NUM)
429 debug_error(DEBUG, "Can't probe file type\n");
436 return MMFILE_FORMAT_FAIL;
443 return MMFILE_FORMAT_SUCCESS;
446 static int _mmfile_format_close(MMFileFormatContext *formatContext, bool clean_all)
448 if (NULL == formatContext) {
449 debug_error(DEBUG, "error: invalid params\n");
450 return MMFILE_FORMAT_FAIL;
453 if (formatContext->Close) {
454 formatContext->Close(formatContext);
455 formatContext->Close = NULL;
458 _CleanupFrameContext(formatContext, clean_all);
461 mmfile_free(formatContext);
463 return MMFILE_FORMAT_SUCCESS;
468 int mmfile_format_open(MMFileFormatContext **formatContext, MMFileSourceType *fileSrc)
472 MMFileFormatContext *formatObject = NULL;
474 if (NULL == fileSrc) {
475 debug_error(DEBUG, "error: invalid params\n");
476 return MMFILE_FORMAT_FAIL;
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;
487 memset(formatObject, 0x00, sizeof(MMFileFormatContext));
489 mmfile_register_io_all();
491 /* parsing file extension */
492 formatObject->filesrc = fileSrc;
494 formatObject->pre_checked = 0; /*not yet format checked.*/
497 * Format detect and validation check.
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;
506 formatObject->pre_checked = 1; /*already file format checked.*/
509 * Open format function.
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;
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; */
525 *formatContext = formatObject;
526 return MMFILE_FORMAT_SUCCESS;
529 formatObject->pre_checked = 0; /*do check file format*/
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;
538 if (formatObject->formatType == index)
541 ret = MMFileFunc[index].Open(formatObject);
542 if (MMFILE_FORMAT_FAIL == ret) {
543 /* _CleanupFrameContext(formatObject, true); */
550 formatObject->formatType = index;
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;
559 formatObject->formatType = index;
560 *formatContext = formatObject;
562 return MMFILE_FORMAT_SUCCESS;
565 _mmfile_format_close(formatObject, true);
566 *formatContext = NULL;
572 int mmfile_format_read_stream(MMFileFormatContext *formatContext)
574 if (NULL == formatContext || NULL == formatContext->ReadStream) {
575 debug_error(DEBUG, "error: invalid params\n");
576 return MMFILE_FORMAT_FAIL;
579 return formatContext->ReadStream(formatContext);
583 int mmfile_format_read_frame(MMFileFormatContext *formatContext, unsigned int timestamp, MMFileFormatFrame *frame)
585 if (NULL == formatContext || NULL == frame || NULL == formatContext->ReadFrame) {
586 debug_error(DEBUG, "error: invalid params\n");
587 return MMFILE_FORMAT_FAIL;
590 return formatContext->ReadFrame(formatContext, timestamp, frame);
594 int mmfile_format_read_tag(MMFileFormatContext *formatContext)
596 if (NULL == formatContext || NULL == formatContext->ReadTag) {
597 debug_error(DEBUG, "error: invalid params\n");
598 return MMFILE_FORMAT_FAIL;
601 return formatContext->ReadTag(formatContext);
606 int mmfile_format_close(MMFileFormatContext *formatContext)
608 return _mmfile_format_close(formatContext, false);