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.
22 #include <string.h> /*memcmp*/
23 #include <stdlib.h> /*malloc*/
24 #include "mm_file_debug.h"
25 #include "mm_file_utils.h"
27 /* Description of return value
32 /***********************************************************************/
33 /* Internal functions */
34 /***********************************************************************/
35 static bool _MMFileSearchID3Tag(MMFileIOHandle *fp, unsigned int *offset);
36 static int _MMFileIsMP3Header(void *header);
37 static bool _MMFileIsMMFHeader(void *header);
38 static int _MMFileIsMPEGTSHeader(MMFileIOHandle *fp);
40 /***********************************************************************/
41 /* MP3 Header Check API */
42 /***********************************************************************/
44 int MMFileFormatIsValidMP3(MMFileIOHandle *pFileIO, const char *mmfileuri, int frameCnt)
46 #define _MMFILE_MP3_HEADER_LENGTH 4
47 #define _MMFILE_MP3_BUFFER_LENGTH 8200
49 MMFileIOHandle *fp = pFileIO;
50 unsigned char buffer[_MMFILE_MP3_BUFFER_LENGTH] = {0, };
51 long long filesize = 0;
52 unsigned int sizeID3 = 0;
53 int readn = 0, i = 0, j = 0;;
54 unsigned int startoffset = 0;
57 int ret = 0, count = 0, offset = 0;
60 mm_file_retvm_if_fails(DEBUG, mmfile_open(&fp, mmfileuri, MMFILE_RDONLY) == MMFILE_UTIL_SUCCESS, MMFILE_UTIL_FAIL);
62 filesize = mmfile_get_size(fp);
64 if (filesize < _MMFILE_MP3_HEADER_LENGTH) {
65 debug_error(DEBUG, "header is too small.");
69 /* Search the existance of ID3 tag */
70 if (!_MMFileSearchID3Tag(fp, &sizeID3)) {
71 debug_error(RELEASE, "Error in searching the ID3 tag");
75 /* set begin and end point at the file */
76 startoffset += sizeID3;
77 endoffset = startoffset + 102400;
78 if (endoffset > filesize - _MMFILE_MP3_HEADER_LENGTH)
79 endoffset = filesize - _MMFILE_MP3_HEADER_LENGTH;
85 while (i < endoffset) {
86 mmfile_seek(fp, i, MMFILE_SEEK_SET);
87 readn = mmfile_read(fp, buffer, _MMFILE_MP3_BUFFER_LENGTH);
88 if (readn < _MMFILE_MP3_HEADER_LENGTH) {
89 debug_error(RELEASE, "read error");
94 for (j = 0; (j <= readn - _MMFILE_MP3_HEADER_LENGTH); j = j + offset) {
95 frameSize = _MMFileIsMP3Header(buffer + j);
101 if ((j + frameSize) >= (endoffset - (i + _MMFILE_MP3_HEADER_LENGTH))) {
105 if ((j + frameSize) >= (readn - _MMFILE_MP3_HEADER_LENGTH)) {
106 debug_msg(RELEASE, "MP3 coner hit %d %d", j, frameSize);
110 frameSize = _MMFileIsMP3Header(buffer + j + frameSize);
115 if (count == frameCnt) {
117 debug_msg(RELEASE, "Header Detected at %d", i + j);
126 /*If j is zero, this loop is infinite */
133 debug_msg(RELEASE, "Header Not Detected at: %d", i + j);
135 if (pFileIO == NULL && fp != NULL)
143 /***********************************************************************/
144 /* AAC Header Check API */
145 /***********************************************************************/
147 int MMFileFormatIsValidAAC(MMFileIOHandle *pFileIO, const char *mmfileuri, int dummy)
149 #define _MMFILE_AAC_HEADER_LENGTH 4
150 #define _MMFILE_AAC_BUFFER_LENGTH 8200
152 MMFileIOHandle *fp = pFileIO;
153 unsigned char buffer[_MMFILE_AAC_BUFFER_LENGTH] = {0, };
154 unsigned int sizeID3 = 0;
155 long long filesize = 0;
156 int readn = 0, i = 0, j = 0;
160 unsigned int sync = 0;
164 mm_file_retvm_if_fails(DEBUG, mmfile_open(&fp, mmfileuri, MMFILE_RDONLY) == MMFILE_UTIL_SUCCESS, MMFILE_UTIL_FAIL);
166 filesize = mmfile_get_size(fp);
168 if (filesize < _MMFILE_AAC_HEADER_LENGTH) {
169 debug_error(DEBUG, "header is too small.");
173 /* Search the existance of ID3 tag */
174 if (!_MMFileSearchID3Tag(fp, &sizeID3)) {
175 debug_error(RELEASE, "Error in searching the ID3 tag");
179 /* set begin and end point at the file */
180 startoffset += sizeID3;
181 endoffset = startoffset + 10240;
182 if (endoffset > filesize - _MMFILE_AAC_HEADER_LENGTH)
183 endoffset = filesize - _MMFILE_AAC_HEADER_LENGTH;
187 while (i < endoffset) {
188 mmfile_seek(fp, i, MMFILE_SEEK_SET);
190 readn = mmfile_read(fp, buffer, _MMFILE_AAC_BUFFER_LENGTH);
192 if (readn < _MMFILE_AAC_HEADER_LENGTH) {
193 debug_error(RELEASE, "read error");
197 debug_msg(RELEASE, "read error. size = %d. i = %d", readn, i);
199 for (j = 0; (j < readn - _MMFILE_AAC_HEADER_LENGTH); j++) {
201 sync = ((buffer[j] << 8) | (buffer[j + 1]));
203 if ((sync & 0xFFF6) == 0xFFF0) {
204 frameSize = (((buffer[j + 3] & 0x03) << 11) | (buffer[j + 4] << 3) | ((buffer[j + 5] & 0xE0) >> 5));
206 if (frameSize == 0) {
210 if ((j + frameSize) >= (endoffset - (i + 2))) {
213 if ((j + frameSize) >= (readn - 2)) {
214 debug_msg(RELEASE, "AAC coner hit %d %d", j, frameSize);
218 sync = ((buffer[j + frameSize] << 8) | (buffer[j + frameSize + 1]));
220 if ((sync & 0xFFF6) == 0xFFF0) {
222 debug_msg(RELEASE, "AAC ADTS Header Detected at %d", i + j);
225 } else if (!memcmp((buffer + j), "ADIF", 4)) {
227 debug_msg(RELEASE, "AAC ADIF Header Detected at %d", i + j);
231 /*If j is zero, this loop is infinite */
239 debug_msg(RELEASE, "Header Detected Failed");
241 if (pFileIO == NULL && fp != NULL)
249 /***********************************************************************/
250 /* OGG Header Check API */
251 /***********************************************************************/
253 int MMFileFormatIsValidOGG(MMFileIOHandle *pFileIO, const char *mmfileuri, int dummy)
255 #define _MMFILE_OGG_HEADER_LENGTH 4
256 #define _MMFILE_OGG_BUFFER_LENGTH 512
257 #define _MMFILE_OGG_CHECK_LIMIT (_MMFILE_OGG_HEADER_LENGTH * 1000)
259 MMFileIOHandle *fp = pFileIO;
260 unsigned char buffer[_MMFILE_OGG_BUFFER_LENGTH] = {0, };
261 unsigned int sizeID3 = 0;
262 long long filesize = 0;
263 int readn = 0, i = 0, j = 0;
270 mm_file_retvm_if_fails(DEBUG, mmfile_open(&fp, mmfileuri, MMFILE_RDONLY) == MMFILE_UTIL_SUCCESS, MMFILE_UTIL_FAIL);
272 filesize = mmfile_get_size(fp);
274 if (filesize < _MMFILE_OGG_HEADER_LENGTH) {
275 debug_error(DEBUG, "header is too small.");
279 /* Search the existance of ID3 tag */
280 if (!_MMFileSearchID3Tag(fp, &sizeID3)) {
281 debug_error(RELEASE, "Error in searching the ID3 tag");
285 /* set begin and end point at the file */
286 startoffset += sizeID3;
287 endoffset = filesize - _MMFILE_OGG_HEADER_LENGTH;
289 check_limit = (endoffset > _MMFILE_OGG_CHECK_LIMIT) ? _MMFILE_OGG_CHECK_LIMIT : endoffset;
292 while (i <= check_limit) {
293 mmfile_seek(fp, i, MMFILE_SEEK_SET);
294 readn = mmfile_read(fp, buffer, _MMFILE_OGG_BUFFER_LENGTH);
295 if (readn < _MMFILE_OGG_HEADER_LENGTH) {
296 debug_error(RELEASE, "read error");
300 for (j = 0; (j <= readn - _MMFILE_OGG_HEADER_LENGTH); j++) {
301 if (!memcmp(buffer + j, "OggS", 4)) {
303 debug_msg(RELEASE, "Header Detected at %d", i + j);
308 memset(buffer, 0x00, _MMFILE_OGG_BUFFER_LENGTH);
314 if (pFileIO == NULL && fp != NULL)
322 /***********************************************************************/
323 /* MIDI Header Check API */
324 /***********************************************************************/
326 int MMFileFormatIsValidMID(MMFileIOHandle *pFileIO, const char *mmfileuri, int dummy)
328 #define _MMFILE_MIDI_HEADER_LENGTH 4
329 #define _MMFILE_MIDI_BUFFER_LENGTH 512
330 #define _MMFILE_MIDI_CHECK_LIMIT (_MMFILE_MIDI_HEADER_LENGTH * 1024)
332 MMFileIOHandle *fp = pFileIO;
333 unsigned char buffer[_MMFILE_MIDI_BUFFER_LENGTH] = {0, };
334 long long filesize = 0;
335 int readn = 0, i = 0, j = 0;
342 mm_file_retvm_if_fails(DEBUG, mmfile_open(&fp, mmfileuri, MMFILE_RDONLY) == MMFILE_UTIL_SUCCESS, MMFILE_UTIL_FAIL);
344 filesize = mmfile_get_size(fp);
346 if (filesize < _MMFILE_MIDI_HEADER_LENGTH) {
347 debug_error(DEBUG, "header is too small.");
351 /* set begin and end point at the file */
353 endoffset = filesize - _MMFILE_MIDI_HEADER_LENGTH;
355 check_limit = (endoffset > _MMFILE_MIDI_CHECK_LIMIT) ? _MMFILE_MIDI_CHECK_LIMIT : endoffset;
358 while (i <= check_limit) {
359 mmfile_seek(fp, i, MMFILE_SEEK_SET);
360 readn = mmfile_read(fp, buffer, _MMFILE_MIDI_BUFFER_LENGTH);
361 if (readn < _MMFILE_MIDI_HEADER_LENGTH) {
362 debug_error(RELEASE, "read error");
366 for (j = 0; (j <= readn - _MMFILE_MIDI_HEADER_LENGTH); j++) {
367 if (!memcmp(buffer + j, "MThd", 4) || !memcmp(buffer + j, "XMF_", 4) || !memcmp(buffer + j, "IREZ", 4)) {
369 debug_msg(RELEASE, "Header Detected at %d", i + j);
374 memset(buffer, 0x00, _MMFILE_MIDI_BUFFER_LENGTH);
380 if (pFileIO == NULL && fp != NULL)
387 /***********************************************************************/
388 /* WAV Header Check API */
389 /***********************************************************************/
391 int MMFileFormatIsValidWAV(MMFileIOHandle *pFileIO, const char *mmfileuri, int dummy)
393 #define _MMFILE_WAV_HEADER_LENGTH 15
395 MMFileIOHandle *fp = pFileIO;
396 unsigned char buffer[_MMFILE_WAV_HEADER_LENGTH] = {0, };
400 mm_file_retvm_if_fails(DEBUG, mmfile_open(&fp, mmfileuri, MMFILE_RDONLY) == MMFILE_UTIL_SUCCESS, MMFILE_UTIL_FAIL);
402 mmfile_seek(fp, 0L, MMFILE_SEEK_SET);
404 if (mmfile_read(fp, buffer, _MMFILE_WAV_HEADER_LENGTH) != _MMFILE_WAV_HEADER_LENGTH) {
405 debug_error(RELEASE, "read error");
409 if (!memcmp(buffer, "RIFF", 4) && !memcmp(buffer + 8, "WAVE", 4)) {
410 debug_msg(RELEASE, "Header Detected");
415 if (pFileIO == NULL && fp != NULL)
423 /***********************************************************************/
424 /* MP4 Header Check API */
425 /***********************************************************************/
427 int MMFileFormatIsValidMP4(MMFileIOHandle *pFileIO, const char *mmfileuri, int dummy)
429 #define _MMFILE_MP4_HEADER_LENGTH 4
430 #define _MMFILE_MP4_CHECK_LIMIT (1024*10) /*10Kbyte*/
431 MMFileIOHandle *fp = pFileIO;
432 unsigned char buffer[_MMFILE_MP4_HEADER_LENGTH] = {0, };
433 long long filesize = 0;
434 unsigned int startoffset = 0;
436 unsigned int check_limit = 0;
439 mm_file_retvm_if_fails(DEBUG, mmfile_open(&fp, mmfileuri, MMFILE_RDONLY) == MMFILE_UTIL_SUCCESS, MMFILE_UTIL_FAIL);
441 filesize = mmfile_get_size(fp);
443 if (filesize < _MMFILE_MP4_HEADER_LENGTH) {
444 debug_error(DEBUG, "header is too small.");
448 /**@note weak check*/
449 check_limit = (filesize > _MMFILE_MP4_CHECK_LIMIT) ? _MMFILE_MP4_CHECK_LIMIT : filesize;
450 for (startoffset = 0; check_limit - (startoffset + _MMFILE_MP4_HEADER_LENGTH) > 0; startoffset++) {
451 mmfile_seek(fp, startoffset, MMFILE_SEEK_SET);
453 if (mmfile_read(fp, buffer, _MMFILE_MP4_HEADER_LENGTH) != _MMFILE_MP4_HEADER_LENGTH) {
454 debug_error(RELEASE, "read error");
459 if (!memcmp(buffer, "moov", 4) || !memcmp(buffer, "mdat", 4) || !memcmp(buffer, "ftyp", 4) ||
460 !memcmp(buffer, "free", 4) || !memcmp(buffer, "uuid", 4) || !memcmp(buffer, "skip", 4) ||
461 !memcmp(buffer, "PICT", 4) || !memcmp(buffer, "wide", 4) || !memcmp(buffer, "prfl", 4)) {
462 debug_msg(RELEASE, "MP4 Header Detected");
469 if (pFileIO == NULL && fp != NULL)
476 /***********************************************************************/
477 /* AVI Header Check API */
478 /***********************************************************************/
480 int MMFileFormatIsValidAVI(MMFileIOHandle *pFileIO, const char *mmfileuri, int dummy)
482 #define _MMFILE_AVI_HEADER_LENGTH 12
484 MMFileIOHandle *fp = pFileIO;
485 unsigned char buffer[_MMFILE_AVI_HEADER_LENGTH] = {0, };
489 mm_file_retvm_if_fails(DEBUG, mmfile_open(&fp, mmfileuri, MMFILE_RDONLY) == MMFILE_UTIL_SUCCESS, MMFILE_UTIL_FAIL);
491 mmfile_seek(fp, 0L, MMFILE_SEEK_SET);
493 if (mmfile_read(fp, buffer, _MMFILE_AVI_HEADER_LENGTH) != _MMFILE_AVI_HEADER_LENGTH) {
494 debug_error(RELEASE, "read error");
498 if (!memcmp(buffer, "RIFF", 4) && !memcmp(buffer + 8, "AVI", 3)) {
499 debug_msg(RELEASE, "Header Detected ");
504 if (pFileIO == NULL && fp != NULL)
512 /***********************************************************************/
513 /* ASF Header Check API */
514 /***********************************************************************/
516 int MMFileFormatIsValidASF(MMFileIOHandle *pFileIO, const char *mmfileuri, int dummy)
518 #define _MMFILE_ASF_HEADER_LENGTH 16
519 MMFileIOHandle *fp = pFileIO;
520 unsigned char buffer[_MMFILE_ASF_HEADER_LENGTH] = {0, };
524 mm_file_retvm_if_fails(DEBUG, mmfile_open(&fp, mmfileuri, MMFILE_RDONLY) == MMFILE_UTIL_SUCCESS, MMFILE_UTIL_FAIL);
526 mmfile_seek(fp, 0L, MMFILE_SEEK_SET);
528 if (mmfile_read(fp, buffer, _MMFILE_ASF_HEADER_LENGTH) != _MMFILE_ASF_HEADER_LENGTH) {
529 debug_error(RELEASE, "read error");
533 /* ID: 30 26 B2 75 8E 66 CF 11 A6 D9 00 AA 00 62 CE 6C */
534 if ((buffer[0] == 0x30) && (buffer[1] == 0x26) && (buffer[2] == 0xB2) && (buffer[3] == 0x75) &&
535 (buffer[4] == 0x8E) && (buffer[5] == 0x66) && (buffer[6] == 0xCF) && (buffer[7] == 0x11) &&
536 (buffer[8] == 0xA6) && (buffer[9] == 0xD9) && (buffer[10] == 0x00) && (buffer[11] == 0xAA) &&
537 (buffer[12] == 0x00) && (buffer[13] == 0x62) && (buffer[14] == 0xCE) && (buffer[15] == 0x6C)) {
538 debug_msg(RELEASE, "Header Detected");
543 if (pFileIO == NULL && fp != NULL)
549 /***********************************************************************/
550 /* WMA Header Check API */
551 /***********************************************************************/
553 int MMFileFormatIsValidWMA(MMFileIOHandle *pFileIO, const char *mmfileuri, int dummy)
555 return MMFileFormatIsValidASF(pFileIO, mmfileuri, dummy);
560 /***********************************************************************/
561 /* WMV Header Check API */
562 /***********************************************************************/
564 int MMFileFormatIsValidWMV(MMFileIOHandle *pFileIO, const char *mmfileuri, int dummy)
566 return MMFileFormatIsValidASF(pFileIO, mmfileuri, dummy);
570 /***********************************************************************/
571 /* MMF Header Check API */
572 /***********************************************************************/
574 int MMFileFormatIsValidMMF(MMFileIOHandle *pFileIO, const char *mmfileuri, int dummy)
576 #define _MMFILE_MMF_HEADER_LENGTH 18
578 MMFileIOHandle *fp = pFileIO;
579 unsigned char buffer[_MMFILE_MMF_HEADER_LENGTH] = {0, };
583 mm_file_retvm_if_fails(DEBUG, mmfile_open(&fp, mmfileuri, MMFILE_RDONLY) == MMFILE_UTIL_SUCCESS, MMFILE_UTIL_FAIL);
585 mmfile_seek(fp, 0L, MMFILE_SEEK_SET);
587 if (mmfile_read(fp, buffer, _MMFILE_MMF_HEADER_LENGTH) != _MMFILE_MMF_HEADER_LENGTH) {
588 debug_error(RELEASE, "read error");
592 if (_MMFileIsMMFHeader(buffer)) {
593 debug_msg(RELEASE, "Header Detected");
598 if (pFileIO == NULL && fp != NULL)
606 /***********************************************************************/
607 /* MMF Header Check API */
608 /***********************************************************************/
610 int MMFileFormatIsValidIMY(MMFileIOHandle *pFileIO, const char *mmfileuri, int dummy)
612 #define _MMFILE_IMY_HEADER_LENGTH 13
614 MMFileIOHandle *fp = pFileIO;
615 unsigned char buffer[_MMFILE_IMY_HEADER_LENGTH] = {0, };
619 mm_file_retvm_if_fails(DEBUG, mmfile_open(&fp, mmfileuri, MMFILE_RDONLY) == MMFILE_UTIL_SUCCESS, MMFILE_UTIL_FAIL);
621 mmfile_seek(fp, 0L, MMFILE_SEEK_SET);
623 if (mmfile_read(fp, buffer, _MMFILE_IMY_HEADER_LENGTH) != _MMFILE_IMY_HEADER_LENGTH) {
624 debug_error(RELEASE, "read error");
628 if (!memcmp(buffer, "BEGIN:IMELODY", 13)) {
629 debug_msg(RELEASE, "Header Detected");
634 if (pFileIO == NULL && fp != NULL)
642 /***********************************************************************/
643 /* AMR Header Check API */
644 /***********************************************************************/
646 int MMFileFormatIsValidAMR(MMFileIOHandle *pFileIO, const char *mmfileuri, int dummy)
648 #define _MMFILE_AMR_MAX_HEADER_SIZE 15
649 #define _MMFILE_AMR_MIN_HEADER_SIZE 6
651 MMFileIOHandle *fp = pFileIO;
652 unsigned char buffer[_MMFILE_AMR_MAX_HEADER_SIZE] = {0, };
656 mm_file_retvm_if_fails(DEBUG, mmfile_open(&fp, mmfileuri, MMFILE_RDONLY) == MMFILE_UTIL_SUCCESS, MMFILE_UTIL_FAIL);
658 mmfile_seek(fp, 0L, MMFILE_SEEK_SET);
660 if (mmfile_read(fp, buffer, _MMFILE_AMR_MAX_HEADER_SIZE) != _MMFILE_AMR_MAX_HEADER_SIZE) {
661 debug_error(RELEASE, "read error");
665 if (!memcmp(buffer, "#!AMR\n", 6) ||
666 !memcmp(buffer, "#!AMR-WB\n", 9) ||
667 !memcmp(buffer, "#!AMR_MC1.0\n", 12) ||
668 !memcmp(buffer, "#!AMR-WB_MC1.0\n", 15)) {
669 debug_msg(RELEASE, "Header Detected");
675 if (pFileIO == NULL && fp != NULL)
681 /***********************************************************************/
682 /* Matroska Header Check API */
683 /***********************************************************************/
685 int MMFileFormatIsValidMatroska(MMFileIOHandle *pFileIO, const char *mmfileuri, int dummy)
687 #define _MMFILE_EBML_MARKER_LENGTH 4
688 #define _MMFILE_MKV_READ_BUFFER_LENGTH 2048
690 MMFileIOHandle *fp = pFileIO;
691 unsigned char buffer[_MMFILE_MKV_READ_BUFFER_LENGTH] = {0, };
694 unsigned long size = 1, n = 1, total = 0;
695 //char probe_data[] = { 'm', 'a', 't', 'r', 'o', 's', 'k', 'a' };
696 /*support webm, add probe data*/
697 const char * probe_data[2] = { "matroska", "webm" };
699 mm_file_retvm_if_fails(DEBUG, mmfile_open(&fp, mmfileuri, MMFILE_RDONLY) == MMFILE_UTIL_SUCCESS, MMFILE_UTIL_FAIL);
701 mmfile_seek(fp, 0L, MMFILE_SEEK_SET);
703 if (mmfile_read(fp, buffer, _MMFILE_MKV_READ_BUFFER_LENGTH) != _MMFILE_MKV_READ_BUFFER_LENGTH) {
704 debug_error(RELEASE, "read error");
709 if (buffer[0] != 0x1A || buffer[1] != 0x45 || buffer[2] != 0xDF || buffer[3] != 0xA3) {
710 debug_msg(RELEASE, "This is not a EBML format");
714 /* length of header */
717 debug_msg(RELEASE, "Initial total header size = [%lu]", total);
719 while (size <= 8 && !(total & len_mask)) {
720 debug_msg(DEBUG, "This case can not be handled yet....");
725 debug_msg(RELEASE, "Final total header size = [%lu]", total);
728 debug_msg(DEBUG, "This case can not be handled yet....");
732 total &= (len_mask - 1);
735 total = (total << 8) | buffer[4 + n++];
736 debug_msg(DEBUG, "This case can not be handled yet....");
739 /* Does the probe data contain the whole header? */
740 if (_MMFILE_MKV_READ_BUFFER_LENGTH < 4 + size + total)
743 /*compare two kinds of probe data*/
744 for (int i = 0; i < 2; i++) {
745 unsigned long probelen = strlen(probe_data[i]);
746 if (total < probelen)
748 for (n = 4 + size ; n <= 4 + size + total - probelen; n++) {
749 if (!memcmp(&buffer[n], probe_data[i], probelen)) {
750 debug_msg(RELEASE, "String %s found!!!", probe_data[i]);
758 if (pFileIO == NULL && fp != NULL)
764 /***********************************************************************/
765 /* QT Header Check API */
766 /***********************************************************************/
768 int MMFileFormatIsValidQT(MMFileIOHandle *pFileIO, const char *mmfileuri, int dummy)
773 /***********************************************************************/
774 /* Flac Header Check API */
775 /***********************************************************************/
777 int MMFileFormatIsValidFLAC(MMFileIOHandle *pFileIO, const char *mmfileuri, int dummy)
779 #define _MMFILE_FLAC_HEADER_LENGTH 5 /*fLaC*/
781 MMFileIOHandle *fp = pFileIO;
782 unsigned char buffer[_MMFILE_FLAC_HEADER_LENGTH] = {0, };
786 mm_file_retvm_if_fails(DEBUG, mmfile_open(&fp, mmfileuri, MMFILE_RDONLY) == MMFILE_UTIL_SUCCESS, MMFILE_UTIL_FAIL);
788 mmfile_seek(fp, 0L, MMFILE_SEEK_SET);
790 if (mmfile_read(fp, buffer, _MMFILE_FLAC_HEADER_LENGTH) != _MMFILE_FLAC_HEADER_LENGTH) {
791 debug_error(RELEASE, "read error");
795 if (!memcmp(buffer, "fLaC", 4)) {
796 debug_msg(RELEASE, "Header Detected");
801 if (pFileIO == NULL && fp != NULL)
807 /***********************************************************************/
808 /* FLV(flash video) Header Check API */
809 /***********************************************************************/
811 int MMFileFormatIsValidFLV(MMFileIOHandle *pFileIO, const char *mmfileuri, int dummy)
813 #define _MMFILE_FLV_HEADER_LENGTH 4 /*FLV*/
815 MMFileIOHandle *fp = pFileIO;
816 unsigned char buffer[_MMFILE_FLV_HEADER_LENGTH] = {0, };
820 mm_file_retvm_if_fails(DEBUG, mmfile_open(&fp, mmfileuri, MMFILE_RDONLY) == MMFILE_UTIL_SUCCESS, MMFILE_UTIL_FAIL);
822 mmfile_seek(fp, 0L, MMFILE_SEEK_SET);
824 if (mmfile_read(fp, buffer, _MMFILE_FLV_HEADER_LENGTH) != _MMFILE_FLV_HEADER_LENGTH) {
825 debug_error(RELEASE, "read error");
829 if (!memcmp(buffer, "FLV", 3)) {
830 debug_msg(RELEASE, "Header Detected");
835 if (pFileIO == NULL && fp != NULL)
842 /***********************************************************************/
843 /* REAL Header Check API */
844 /***********************************************************************/
846 int MMFileFormatIsValidREAL(MMFileIOHandle *pFileIO, const char *mmfileuri, int dummy)
848 #define _MMFILE_RMVB_HEADER_LENGTH 4 /*RMF*/
850 MMFileIOHandle *fp = pFileIO;
851 unsigned char buffer[_MMFILE_RMVB_HEADER_LENGTH] = {0, };
855 mm_file_retvm_if_fails(DEBUG, mmfile_open(&fp, mmfileuri, MMFILE_RDONLY) == MMFILE_UTIL_SUCCESS, MMFILE_UTIL_FAIL);
857 mmfile_seek(fp, 0L, MMFILE_SEEK_SET);
859 if (mmfile_read(fp, buffer, _MMFILE_RMVB_HEADER_LENGTH) != _MMFILE_RMVB_HEADER_LENGTH) {
860 debug_error(RELEASE, "read error");
864 if (!memcmp(buffer, ".RMF", 4)) {
865 debug_msg(RELEASE, "Header Detected");
870 if (pFileIO == NULL && fp != NULL)
876 /***********************************************************************/
877 /* MPEGTS Header Check API */
878 /***********************************************************************/
879 #define MPEGTS_NONE 0x00
880 #define MPEGTS_FECE 0x10
881 #define MPEGTS_DVHS 0x20
882 #define MPEGTS_PACKET 0x40
884 #define TS_PACKET_SIZE 188
885 #define TS_DVHS_PACKET_SIZE 192
886 #define TS_FEC_PACKET_SIZE 204
887 #define TS_MAX_PACKET_SIZE 204
890 int MMFileFormatIsValidMPEGTS(MMFileIOHandle *pFileIO, const char *mmfileuri, int dummy)
892 MMFileIOHandle *fp = pFileIO;
893 unsigned char buffer[TS_MAX_PACKET_SIZE] = {0, };
897 mm_file_retvm_if_fails(DEBUG, mmfile_open(&fp, mmfileuri, MMFILE_RDONLY) == MMFILE_UTIL_SUCCESS, MMFILE_UTIL_FAIL);
899 mmfile_seek(fp, 0L, MMFILE_SEEK_SET);
901 if (mmfile_read(fp, buffer, TS_MAX_PACKET_SIZE) != TS_MAX_PACKET_SIZE) {
902 debug_error(RELEASE, "read error");
906 if (_MMFileIsMPEGTSHeader(fp) != MPEGTS_NONE) {
907 debug_msg(RELEASE, "Header Detected");
912 if (pFileIO == NULL && fp != NULL)
918 /***********************************************************************/
919 /* MPEG-PS Header Check API */
920 /***********************************************************************/
922 int MMFileFormatIsValidMPEGPS(MMFileIOHandle *pFileIO, const char *mmfileuri, int dummy)
924 #define _MMFILE_MPEGPS_HEADER_LENGTH 4
926 MMFileIOHandle *fp = pFileIO;
927 unsigned char buffer[_MMFILE_MPEGPS_HEADER_LENGTH] = {0, };
931 mm_file_retvm_if_fails(DEBUG, mmfile_open(&fp, mmfileuri, MMFILE_RDONLY) == MMFILE_UTIL_SUCCESS, MMFILE_UTIL_FAIL);
933 mmfile_seek(fp, 0L, MMFILE_SEEK_SET);
935 if (mmfile_read(fp, buffer, _MMFILE_MPEGPS_HEADER_LENGTH) != _MMFILE_MPEGPS_HEADER_LENGTH) {
936 debug_error(RELEASE, "read error");
940 if ((buffer[0] == 0x00) && (buffer[1] == 0x00) && (buffer[2] == 0x01) && (buffer[3] == 0xba)) {
941 debug_msg(RELEASE, "Header Detected");
946 if (pFileIO == NULL && fp != NULL)
952 /***********************************************************************/
953 /* MPEG AUDIO Header Check API */
954 /***********************************************************************/
956 int MMFileFormatIsValidMPEGAUDIO(MMFileIOHandle *pFileIO, const char *mmfileuri, int dummy)
958 #define _MMFILE_MPEGAUDIO_HEADER_LENGTH 4
960 MMFileIOHandle *fp = pFileIO;
961 unsigned char buffer[_MMFILE_MPEGAUDIO_HEADER_LENGTH] = {0, };
965 mm_file_retvm_if_fails(DEBUG, mmfile_open(&fp, mmfileuri, MMFILE_RDONLY) == MMFILE_UTIL_SUCCESS, MMFILE_UTIL_FAIL);
967 mmfile_seek(fp, 0L, MMFILE_SEEK_SET);
969 if (mmfile_read(fp, buffer, _MMFILE_MPEGAUDIO_HEADER_LENGTH) != _MMFILE_MPEGAUDIO_HEADER_LENGTH) {
970 debug_error(RELEASE, "read error");
973 /* mpeg audio version 1, layer 1 header, FE: protected by CRC ,FF: not protected */
974 /* mpeg audio version 2, layer 1 header, F7: not protected */
975 if ((buffer[0] == 0xFF) && ((buffer[1] == 0xFE) || (buffer[1] == 0xFF) || (buffer[1] == 0xF7))) {
976 debug_msg(RELEASE, "Header Detected");
981 if (pFileIO == NULL && fp != NULL)
987 /***********************************************************************/
988 /* MPEG VIDEO Header Check API */
989 /***********************************************************************/
991 int MMFileFormatIsValidMPEGVIDEO(MMFileIOHandle *pFileIO, const char *mmfileuri, int dummy)
993 #define _MMFILE_MPEGVIDEO_HEADER_LENGTH 4
995 MMFileIOHandle *fp = pFileIO;
996 unsigned char buffer[_MMFILE_MPEGVIDEO_HEADER_LENGTH] = {0, };
1000 mm_file_retvm_if_fails(DEBUG, mmfile_open(&fp, mmfileuri, MMFILE_RDONLY) == MMFILE_UTIL_SUCCESS, MMFILE_UTIL_FAIL);
1002 mmfile_seek(fp, 0L, MMFILE_SEEK_SET);
1004 if (mmfile_read(fp, buffer, _MMFILE_MPEGVIDEO_HEADER_LENGTH) != _MMFILE_MPEGVIDEO_HEADER_LENGTH) {
1005 debug_error(RELEASE, "read error");
1009 if ((buffer[0] == 0x00) && (buffer[1] == 0x00) && (buffer[2] == 0x01) && (buffer[3] == 0xb3)) {
1010 debug_msg(RELEASE, "Header Detected");
1015 if (pFileIO == NULL && fp != NULL)
1021 /***********************************************************************/
1022 /* AIFF Header Check API */
1023 /***********************************************************************/
1025 int MMFileFormatIsValidAIFF(MMFileIOHandle *pFileIO, const char *mmfileuri, int dummy)
1027 #define _MMFILE_AIFF_HEADER_LENGTH 13
1029 MMFileIOHandle *fp = pFileIO;
1030 unsigned char buffer[_MMFILE_AIFF_HEADER_LENGTH] = {0, };
1034 mm_file_retvm_if_fails(DEBUG, mmfile_open(&fp, mmfileuri, MMFILE_RDONLY) == MMFILE_UTIL_SUCCESS, MMFILE_UTIL_FAIL);
1036 mmfile_seek(fp, 0L, MMFILE_SEEK_SET);
1038 if (mmfile_read(fp, buffer, _MMFILE_AIFF_HEADER_LENGTH) != _MMFILE_AIFF_HEADER_LENGTH) {
1039 debug_error(RELEASE, "read error");
1043 if (!memcmp(buffer, "FORM", 4) && !memcmp(buffer + 8, "AIFF", 4)) {
1044 debug_msg(RELEASE, "Header Detected");
1049 if (pFileIO == NULL && fp != NULL)
1056 int MMFileFormatIsValidAPE(MMFileIOHandle *pFileIO, const char *mmfileuri, int dummy)
1058 #define _MMFILE_APE_HEADER_LENGTH 4 /*APE*/
1060 MMFileIOHandle *fp = pFileIO;
1061 unsigned char buffer[_MMFILE_APE_HEADER_LENGTH] = {0, };
1065 mm_file_retvm_if_fails(DEBUG, mmfile_open(&fp, mmfileuri, MMFILE_RDONLY) == MMFILE_UTIL_SUCCESS, MMFILE_UTIL_FAIL);
1067 mmfile_seek(fp, 0L, MMFILE_SEEK_SET);
1069 if (mmfile_read(fp, buffer, _MMFILE_APE_HEADER_LENGTH) != _MMFILE_APE_HEADER_LENGTH) {
1070 debug_error(RELEASE, "read error");
1074 if (!memcmp(buffer, "MAC ", 4)) {
1075 debug_msg(RELEASE, "Header Detected");
1080 if (pFileIO == NULL && fp != NULL)
1086 /***********************************************************************/
1087 /* Implementation of Internal Functions */
1088 /***********************************************************************/
1089 static bool _MMFileIsMMFHeader(void *header)
1091 #define _MMFILE_MMF_TYPE_POSITION 0x11
1092 unsigned char *s = header;
1094 mm_file_retv_if_fails(memcmp(s, "MMMD", 4) == 0, false);
1096 /* warning: comparison is always true due to limited range of data type */
1097 if (s[_MMFILE_MMF_TYPE_POSITION] <= 0x2F)
1100 if (((s[_MMFILE_MMF_TYPE_POSITION] >= 0x30) && (s[_MMFILE_MMF_TYPE_POSITION] <= 0x38)) /* MA3, MA5 type */
1101 || ((s[_MMFILE_MMF_TYPE_POSITION] >= 0x40) && (s[_MMFILE_MMF_TYPE_POSITION] <= 0x48))
1102 || ((s[_MMFILE_MMF_TYPE_POSITION] >= 0x50) && (s[_MMFILE_MMF_TYPE_POSITION] <= 0x58))
1103 || ((s[_MMFILE_MMF_TYPE_POSITION] == 0xF0))) {
1111 static int _MMFileIsMPEGTSHeader(MMFileIOHandle *fp)
1113 unsigned char buffer[TS_MAX_PACKET_SIZE] = {0, };
1114 unsigned char *s = NULL;
1115 unsigned long startoffset = 0;
1117 mmfile_seek(fp, 0, MMFILE_SEEK_SET);
1118 mmfile_read(fp, buffer, TS_MAX_PACKET_SIZE);
1120 s = (unsigned char *)memchr(buffer, 0x47, TS_MAX_PACKET_SIZE);
1121 mm_file_retv_if_fails(s, MPEGTS_NONE);
1123 startoffset = s - buffer + 1;
1125 memset(&buffer, 0x00, TS_MAX_PACKET_SIZE);
1127 mmfile_seek(fp, startoffset, MMFILE_SEEK_SET);
1128 mmfile_read(fp, buffer, TS_MAX_PACKET_SIZE);
1130 if (buffer[TS_PACKET_SIZE - 1] & 0x47)
1131 return MPEGTS_PACKET;
1132 else if (buffer[TS_DVHS_PACKET_SIZE - 1] & 0x47)
1134 else if (buffer[TS_FEC_PACKET_SIZE - 1] & 0x47)
1140 static int _MMFileIsMP3Header(void *header)
1142 unsigned int head = 0;
1143 unsigned char *headc = header;
1144 unsigned int bitrate, layer, length/*, mode*/;
1145 unsigned int coef, samplerate, version/*, channels*/;
1146 static const unsigned int mp3types_bitrates[2][3][16] = {
1147 { {0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448,},
1148 {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384,},
1149 {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320,}
1151 { {0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256,},
1152 {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160,},
1153 {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160,}
1157 static const unsigned int mp3types_freqs[3][3] = {
1158 {11025, 12000, 8000},
1159 {22050, 24000, 16000},
1160 {44100, 48000, 32000}
1163 static const unsigned int mp3FrameCoef[4][4] = {
1171 head = MMFILE_CONVERT_INT(headc);
1172 mm_file_retv_if_fails((head & 0xffe00000) == 0xffe00000, 0);
1174 /* we don't need extension, copyright, original or
1175 * emphasis for the frame length */
1179 /*mode = head & 0x3;*/
1183 length = head & 0x1;
1186 /* sampling frequency */
1187 samplerate = head & 0x3;
1188 mm_file_retv_if_fails(samplerate != 3, 0);
1193 bitrate = head & 0xF;
1194 mm_file_retv_if_fails(bitrate != 15, 0);
1196 /* ignore error correction, too */
1200 layer = 4 - (head & 0x3);
1201 mm_file_retv_if_fails(layer != 4, 0);
1205 /* version 0=MPEG2.5; 2=MPEG2; 3=MPEG1 */
1206 version = head & 0x3;
1207 mm_file_retv_if_fails(version != 1, 0);
1210 /*channels = (mode == 3) ? 1 : 2;*/
1211 samplerate = mp3types_freqs[version > 0 ? version - 1 : 0][samplerate];
1214 bitrate = mp3types_bitrates[version == 3 ? 0 : 1][layer - 1][bitrate];
1215 coef = mp3FrameCoef[version][layer];
1217 length = length * 4;
1219 length = length + ((coef * bitrate * 1000) / samplerate);
1225 static bool _MMFileSearchID3Tag(MMFileIOHandle *fp, unsigned int *offset)
1227 #define _MMFILE_MP3_TAGV2_HEADER_LEN 10
1229 unsigned char tagHeader[_MMFILE_MP3_TAGV2_HEADER_LEN] = {0, };
1230 unsigned int tagInfoSize = 0;
1231 unsigned int acc_tagsize = 0;
1239 mmfile_seek(fp, 0, MMFILE_SEEK_SET);
1243 if (mmfile_read(fp, tagHeader, _MMFILE_MP3_TAGV2_HEADER_LEN) != _MMFILE_MP3_TAGV2_HEADER_LEN) {
1244 debug_error(RELEASE, "read error occured.");
1248 if (memcmp(tagHeader, "ID3", 3) == 0) {
1249 debug_msg(RELEASE, "'ID3' found.");
1251 debug_msg(RELEASE, "'ID3' not found.");
1255 /**@note weak id3v2 tag checking*/
1256 if (tagHeader[3] != 0xFF && tagHeader[4] != 0xFF &&
1257 (tagHeader[6] & 0x80) == 0 && (tagHeader[7] & 0x80) == 0 &&
1258 (tagHeader[8] & 0x80) == 0 && (tagHeader[9] & 0x80) == 0) {
1259 debug_msg(RELEASE, "good ID3V2 tag.");
1261 debug_warning(DEBUG, "It's bad ID3V2 tag.");
1265 tagVersion = tagHeader[3];
1267 mm_file_retvm_if_fails(RELEASE, tagVersion <= 4, ret);
1269 encSize = MMFILE_CONVERT_INT(&tagHeader[6]);
1270 tagInfoSize = _MMFILE_MP3_TAGV2_HEADER_LEN;
1271 tagInfoSize += (((encSize & 0x0000007F) >> 0) | ((encSize & 0x00007F00) >> 1) | ((encSize & 0x007F0000) >> 2) | ((encSize & 0x7F000000) >> 3));
1273 acc_tagsize += tagInfoSize;
1274 debug_msg(RELEASE, "tag size: %u, offset: %u", tagInfoSize, acc_tagsize);
1276 mmfile_seek(fp, acc_tagsize, MMFILE_SEEK_SET);
1277 *offset = acc_tagsize;
1281 /** Some contents has many ID3 tag. Use last one */
1282 goto _START_TAG_SEARCH;