Tizen 2.1 base
[platform/core/multimedia/libmm-fileinfo.git] / utils / mm_file_util_validity.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 <string.h>     /*memcmp*/
23 #include <stdlib.h>     /*malloc*/
24 #include <mm_error.h>
25 #include <mm_debug.h>
26 #include "mm_file_utils.h"
27
28 /* Description of return value
29  * 0: false
30  * 1: true
31  */
32
33 /***********************************************************************/
34 /*                     Internal functions                              */
35 /***********************************************************************/
36 static int _MMFileSearchID3Tag (MMFileIOHandle *fp, unsigned int *offset);
37 static int _MMFileIsMP3Header  (void *header);
38 static int _MMFileIsOGGHeader  (void *header);
39 static int _MMFileIsMP4Header  (void *header);
40 static int _MMFileIsWAVHeader  (void *header);
41 static int _MMFileIsAVIHeader  (void *header);
42 static int _MMFileIsMIDHeader  (void *header);
43 static int _MMFileIsMMFHeader  (void *header);
44 static int _MMFileIsIMYHeader  (void *header);
45 static int _MMFileIsASFHeader  (void *header);
46 static int _MMFileIsAMRHeader  (void *header);
47 static int _MMFileIsFLACHeader  (void *header);
48 static int _MMFileIsFLVHeader  (void *header);
49
50
51
52 /***********************************************************************/
53 /*                     MP3 Header Check API                            */
54 /***********************************************************************/
55 EXPORT_API
56 int MMFileFormatIsValidMP3 (const char *mmfileuri, int frameCnt)
57 {
58 #define _MMFILE_MP3_HEADER_LENGTH   4
59 #define _MMFILE_MP3_BUFFER_LENGTH   8200
60
61         MMFileIOHandle *fp = NULL;
62         unsigned char *buffer=NULL;
63         long long  filesize = 0;
64         unsigned int  sizeID3 = 0;
65         int           readed = 0;
66         unsigned int  startoffset = 0;
67         unsigned int  endoffset = 0;
68         unsigned int  i = 0, j = 0;
69         int ret = 0,frameSize,count,offset;
70
71         ret = mmfile_open (&fp, mmfileuri, MMFILE_RDONLY);
72         if(ret == MMFILE_UTIL_FAIL) {
73                 debug_error ("error: mmfile_open\n");
74                 goto exit;
75         }
76
77         mmfile_seek (fp, 0L, MMFILE_SEEK_END);
78         filesize = mmfile_tell (fp);
79         mmfile_seek (fp, 0L, MMFILE_SEEK_SET);
80
81         if (filesize < _MMFILE_MP3_HEADER_LENGTH) {
82                 debug_error ( "header is too small.\n");
83                 ret = 0;
84                 goto exit;
85         }
86
87         /* Search the existance of ID3 tag */
88         ret = _MMFileSearchID3Tag (fp, &sizeID3);
89         if (ret == 0) {
90                 debug_error("Error in searching the ID3 tag\n");
91                 goto exit;
92         }
93
94         ret = 0;
95
96         /* set begin and end point at the file */
97         startoffset += sizeID3;
98         endoffset = startoffset + 102400;
99         if(endoffset > filesize - _MMFILE_MP3_HEADER_LENGTH)
100                 endoffset = filesize - _MMFILE_MP3_HEADER_LENGTH;
101         
102         /* find sync bit */
103         i = startoffset;
104         count = 0;
105         
106         buffer =  mmfile_malloc (_MMFILE_MP3_BUFFER_LENGTH * sizeof(char));
107
108         if (NULL == buffer) {
109                 debug_error("Error in allocating memory for MP3 buffer\n");
110                 goto exit;
111         }
112
113         while (i < endoffset) {
114                 mmfile_seek (fp, i, MMFILE_SEEK_SET);
115                 readed = mmfile_read (fp, buffer, _MMFILE_MP3_BUFFER_LENGTH);
116                 if (readed < _MMFILE_MP3_HEADER_LENGTH) {
117                         debug_error ( "read error. size = %d. Maybe end of file.\n", readed);
118                         ret = 0;
119                         break;
120                 }
121
122                 offset = 1;
123                 for (j = 0; (j <= readed - _MMFILE_MP3_HEADER_LENGTH); j = j + offset) {
124                         frameSize = _MMFileIsMP3Header (buffer+j);
125
126                         offset = 1;
127                         
128                         if (frameSize) {
129                                 
130                                 if((j+frameSize) >= (endoffset-(i+_MMFILE_MP3_HEADER_LENGTH))) {
131                                         goto failMP3;
132                                 }
133
134                                 if((j+frameSize) >= (readed - _MMFILE_MP3_HEADER_LENGTH)) {
135                                         #ifdef __MMFILE_TEST_MODE__
136                                         debug_msg ( "MP3 coner hit %d %d\n", j, frameSize);
137                                         #endif
138                                         break;
139                                 }
140
141                                 frameSize = _MMFileIsMP3Header (buffer+j+frameSize);
142
143                                 if(frameSize) {
144                                         offset = frameSize;
145                                         count++;
146                                         if(count == frameCnt) {
147                                                 ret = 1;
148                                                 #ifdef __MMFILE_TEST_MODE__
149                                                 debug_msg ( "Header Detected at %d\n", i+j);
150                                                 #endif
151                                                 goto exit;
152                                         }
153                                 } else {
154                                         offset = 1;
155                                 }
156                         }
157                 }
158                 i = i + j;
159         }
160
161 failMP3:
162         #ifdef __MMFILE_TEST_MODE__
163         debug_msg ( "Header Not Detected at: %d\n",i+j);
164         #endif
165 exit:
166
167         if(buffer) {
168                 mmfile_free (buffer);
169         }
170
171         if (fp) {
172                 mmfile_close (fp);
173         }
174
175         return ret;
176 }
177
178
179
180 /***********************************************************************/
181 /*                     AAC Header Check API                            */
182 /***********************************************************************/
183 EXPORT_API
184 int MMFileFormatIsValidAAC (const char *mmfileuri)
185 {
186 #define _MMFILE_AAC_HEADER_LENGTH   4
187 #define _MMFILE_AAC_BUFFER_LENGTH   8200
188
189         MMFileIOHandle *fp = NULL;
190         unsigned char *buffer=NULL;
191         unsigned int  sizeID3 = 0;
192         long long     filesize = 0;
193         int           readed = 0;
194         unsigned int  startoffset = 0;
195         unsigned int  endoffset = 0;
196         unsigned int  i = 0, j = 0;
197         int ret = 0;
198         unsigned int sync,frameSize;
199
200         if (NULL == mmfileuri) {
201                 debug_error ("file source is NULL\n");
202                 return ret;
203         }
204
205         ret = mmfile_open (&fp, mmfileuri, MMFILE_RDONLY);
206         if (ret == MMFILE_UTIL_FAIL) {
207                 debug_error ("error: mmfile_open\n");
208                 goto exit;
209         }
210
211         /* Initialize the members of handle */
212         mmfile_seek (fp, 0, MMFILE_SEEK_END);
213         filesize = mmfile_tell(fp);
214         mmfile_seek (fp, 0, MMFILE_SEEK_SET);
215
216         if (filesize < _MMFILE_AAC_HEADER_LENGTH) {
217                 debug_error ( "header is too small.\n");
218                 ret = 0;
219                 goto exit;
220         }
221
222         /* Search the existance of ID3 tag */
223         ret = _MMFileSearchID3Tag (fp, &sizeID3);
224         if (ret == 0) {
225                 debug_error("Error in searching the ID3 tag\n");
226                 goto exit;
227         }
228
229         ret = 0;
230
231         /* set begin and end point at the file */
232         startoffset += sizeID3;
233         endoffset = startoffset + 10240;
234         if(endoffset > filesize - _MMFILE_AAC_HEADER_LENGTH)
235                 endoffset = filesize - _MMFILE_AAC_HEADER_LENGTH;
236         
237         buffer = mmfile_malloc (_MMFILE_AAC_BUFFER_LENGTH * sizeof(char));
238
239         if (NULL == buffer) {
240                 debug_error("Error in allocating memory for AAC buffer\n");
241                 goto exit;
242         }
243         
244         i = startoffset;
245
246         while (i < endoffset) {
247                 mmfile_seek (fp, i, MMFILE_SEEK_SET);
248
249                 readed = mmfile_read (fp, buffer, _MMFILE_AAC_BUFFER_LENGTH);
250         
251                 if (readed < _MMFILE_AAC_HEADER_LENGTH) {
252                         debug_error ( "read error. size = %d. Maybe end of file.\n", readed);
253                         ret = 0;
254                         break;
255                 }
256
257                 #ifdef __MMFILE_TEST_MODE__
258                 debug_msg ( "read error. size = %d. i = %d\n", readed,i);
259                 #endif
260                 for(j=0; (j < readed - _MMFILE_AAC_HEADER_LENGTH); j++) {
261
262                         sync = ((buffer[j]<<8)|(buffer[j+1]));
263
264                         if ( (sync & 0xFFF6) == 0xFFF0) {
265                                 frameSize = (((buffer[j+3]&0x03)<<11) | (buffer[j+4]<<3) | ((buffer[j+5]&0xE0)>>5));
266
267                                 if(frameSize == 0 ) {
268                                         continue; 
269                                 }
270
271                                 if((j+frameSize) >= (endoffset-(i+2))) {
272                                         goto fail;
273                                 }
274                                 if((j+frameSize) >= (readed - 2)) {
275                                         #ifdef __MMFILE_TEST_MODE__
276                                         debug_msg ( "AAC coner hit %d %d\n", j, frameSize);
277                                         #endif
278                                         break;
279                                 }
280
281                                 sync = ( (buffer[j+frameSize]<<8) | (buffer[j+frameSize+1]));
282
283                                 if ((sync & 0xFFF6) == 0xFFF0) {
284                                         ret = 1;
285                                         #ifdef __MMFILE_TEST_MODE__
286                                         debug_msg ( "AAC ADTS Header Detected at %d\n", i+j);
287                                         #endif
288                                         goto exit;
289                                 }
290                         } else if (!memcmp((buffer+j),"ADIF",4)) {
291                                 ret = 1;
292                                 #ifdef __MMFILE_TEST_MODE__
293                                 debug_msg ( "AAC ADIF Header Detected at %d\n", i+j);
294                                 #endif
295                                 goto exit;
296                         }
297                 }
298                 i = i + j;
299         }
300
301
302 fail:
303         #ifdef __MMFILE_TEST_MODE__
304         debug_msg ( "Header Detected Failed\n");
305         #endif
306
307 exit:
308         if (buffer) {
309                 mmfile_free (buffer);
310         }
311
312         if (fp) {
313                 mmfile_close (fp);
314         }
315
316         return ret;
317 }
318
319
320
321 /***********************************************************************/
322 /*                     OGG Header Check API                            */
323 /***********************************************************************/
324 EXPORT_API
325 int MMFileFormatIsValidOGG (const char *mmfileuri)
326 {
327 #define _MMFILE_OGG_HEADER_LENGTH   4
328 #define _MMFILE_OGG_BUFFER_LENGTH   512
329 #define _MMFILE_OGG_CHECK_LIMIT         (_MMFILE_OGG_HEADER_LENGTH * 1000)
330
331         MMFileIOHandle *fp = NULL;
332         unsigned char buffer[_MMFILE_OGG_BUFFER_LENGTH] = {0,};
333         unsigned int  sizeID3 = 0;
334         long long     filesize = 0;
335         int           readed = 0;
336         unsigned int  startoffset = 0;
337         unsigned int  endoffset = 0;
338         unsigned int  i = 0, j = 0;
339         int ret = 0;
340         unsigned int check_limit = 0;
341
342         if (NULL == mmfileuri) {
343                 debug_error ("file source is NULL\n");
344                 ret = 0;
345                 return ret;
346         }
347
348         ret = mmfile_open (&fp, mmfileuri, MMFILE_RDONLY);
349         if (ret == MMFILE_UTIL_FAIL) {
350                 debug_error ("error: mmfile_open\n");
351                 ret = 0;
352                 goto exit;
353         }
354
355         /* Initialize the members of handle */
356         mmfile_seek (fp, 0, MMFILE_SEEK_END);
357         filesize = mmfile_tell(fp);
358         mmfile_seek (fp, 0, MMFILE_SEEK_SET);
359
360         if (filesize < _MMFILE_OGG_HEADER_LENGTH) {
361                 debug_error ( "header is too small.\n");
362                 ret = 0;
363                 goto exit;
364         }
365
366         /* Search the existance of ID3 tag */
367         ret = _MMFileSearchID3Tag (fp, &sizeID3);
368         if(ret == 0) {
369                 debug_error("Error in searching the ID3 tag\n");
370                 goto exit;
371         }
372
373         ret = 0;
374
375         /* set begin and end point at the file */
376         startoffset += sizeID3;
377         endoffset = filesize - _MMFILE_OGG_HEADER_LENGTH;
378
379         check_limit = (endoffset > _MMFILE_OGG_CHECK_LIMIT) ? _MMFILE_OGG_CHECK_LIMIT : endoffset;
380
381         i = startoffset;
382         while (i <= check_limit) {
383                 mmfile_seek (fp, i, MMFILE_SEEK_SET);
384                 readed = mmfile_read (fp, buffer, _MMFILE_OGG_BUFFER_LENGTH);
385                 if (readed < _MMFILE_OGG_HEADER_LENGTH) {
386                         debug_error ( "read error. size = %d. Maybe end of file.\n", readed);
387                         ret = 0;
388                         break;
389                 }
390
391                 for (j = 0; (j <= readed - _MMFILE_OGG_HEADER_LENGTH); j++) {
392                         if (1 == _MMFileIsOGGHeader (buffer+j)) {
393                                 ret = 1;
394                                 #ifdef __MMFILE_TEST_MODE__
395                                 debug_msg ( "Header Detected at %d\n", i+j);
396                                 #endif
397                                 goto exit;
398                         }
399                 }
400
401                 memset (buffer, 0x00, _MMFILE_OGG_BUFFER_LENGTH);
402
403                 i = i + j;
404         }
405
406 exit:
407         if (fp) {
408                 mmfile_close (fp);
409         }
410
411         return ret;
412 }
413
414
415
416 /***********************************************************************/
417 /*                     MIDI Header Check API                           */
418 /***********************************************************************/
419 EXPORT_API
420 int MMFileFormatIsValidMID (const char *mmfileuri)
421 {
422 #define _MMFILE_MIDI_HEADER_LENGTH 4
423 #define _MMFILE_MIDI_BUFFER_LENGTH 512
424 #define _MMFILE_MIDI_CHECK_LIMIT        (_MMFILE_MIDI_HEADER_LENGTH * 1024)
425
426         MMFileIOHandle *fp = NULL;
427         unsigned char buffer[_MMFILE_MIDI_BUFFER_LENGTH] = {0,};
428         long long     filesize = 0;
429         int           readed = 0;
430         unsigned int  startoffset = 0;
431         unsigned int  endoffset = 0;
432         unsigned int  i = 0, j = 0;
433         int ret = 0;
434         unsigned int check_limit = 0;
435
436         if (NULL == mmfileuri) {
437                 debug_error ("file source is NULL\n");
438                 return ret;
439         }
440
441         ret = mmfile_open (&fp, mmfileuri, MMFILE_RDONLY);
442         if (ret == MMFILE_UTIL_FAIL) {
443                 debug_error ("error: mmfile_open\n");
444                 goto exit;
445         }
446
447         /* Initialize the members of handle */
448         mmfile_seek (fp, 0, MMFILE_SEEK_END);
449         filesize = mmfile_tell(fp);
450         mmfile_seek (fp, 0, MMFILE_SEEK_SET);
451
452         if (filesize < _MMFILE_MIDI_HEADER_LENGTH) {
453                 debug_error ( "header is too small.\n");
454                 ret = 0;
455                 goto exit;
456         }
457
458         ret = 0;
459
460         /* set begin and end point at the file */
461         startoffset = 0;
462         endoffset = filesize - _MMFILE_MIDI_HEADER_LENGTH;
463
464         check_limit = (endoffset > _MMFILE_MIDI_CHECK_LIMIT) ? _MMFILE_MIDI_CHECK_LIMIT : endoffset;
465
466         i = startoffset;
467         while (i <= check_limit) {
468                 mmfile_seek (fp, i, MMFILE_SEEK_SET);
469                 readed = mmfile_read (fp, buffer, _MMFILE_MIDI_BUFFER_LENGTH);
470                 if (readed < _MMFILE_MIDI_HEADER_LENGTH) {
471                         debug_error ( "read error. size = %d. Maybe end of file.\n", readed);
472                         ret = 0;
473                         break;
474                 }
475
476                 for (j = 0; (j <= readed - _MMFILE_MIDI_HEADER_LENGTH); j++) {
477                         if (1 == _MMFileIsMIDHeader (buffer+j)) {
478                                 ret = 1;
479                                 #ifdef __MMFILE_TEST_MODE__
480                                 debug_msg ( "Header Detected at %d\n", i+j);
481                                 #endif
482                                 goto exit;
483                         }
484                 }
485
486                 memset (buffer, 0x00, _MMFILE_MIDI_BUFFER_LENGTH);
487
488                 i = i + j;
489         }
490
491 exit:
492         if (fp) {
493                 mmfile_close (fp);
494         }
495
496         return ret;
497 }
498
499
500 /***********************************************************************/
501 /*                     WAV Header Check API                            */
502 /***********************************************************************/
503 EXPORT_API
504 int MMFileFormatIsValidWAV (const char *mmfileuri)
505 {
506 #define _MMFILE_WAV_HEADER_LENGTH 15
507
508         MMFileIOHandle *fp = NULL;
509         unsigned char buffer[_MMFILE_WAV_HEADER_LENGTH] = {0,};
510         long long     filesize = 0;
511         int           readed = 0;
512         unsigned int  startoffset = 0;
513         int ret = 0;
514
515         if (NULL == mmfileuri) {
516                 debug_error ("file source is NULL\n");
517                 return ret;
518         }
519
520         ret = mmfile_open (&fp, mmfileuri, MMFILE_RDONLY);
521         if (ret == MMFILE_UTIL_FAIL) {
522                 debug_error ("error: mmfile_open\n");
523                 goto exit;
524         }
525
526          /* Initialize the members of handle */
527         mmfile_seek (fp, 0, MMFILE_SEEK_END);
528         filesize = mmfile_tell(fp);
529         mmfile_seek (fp, 0, MMFILE_SEEK_SET);
530
531         if (filesize < _MMFILE_WAV_HEADER_LENGTH) {
532                 debug_error ( "header is too small.\n");
533                 ret = 0;
534                 goto exit;
535         }
536
537         ret = 0;
538         
539         /* set begin and end point at the file */
540         startoffset = 0;
541         
542         mmfile_seek (fp, startoffset, MMFILE_SEEK_SET);
543
544         readed = mmfile_read (fp, buffer, _MMFILE_WAV_HEADER_LENGTH);
545         if (_MMFILE_WAV_HEADER_LENGTH != readed) {
546                 debug_error ( "read error. size = %d. Maybe end of file.\n", readed);
547                 ret = 0;
548                 goto exit;
549         }
550
551         if (1 == _MMFileIsWAVHeader (buffer)) {
552                 #ifdef __MMFILE_TEST_MODE__
553                 debug_msg ( "Header Detected\n");
554                 #endif
555                 ret = 1;
556                 goto exit;
557         }
558
559
560 exit:
561         if (fp) {
562                 mmfile_close (fp);
563         }
564
565         return ret;
566 }
567
568
569
570 /***********************************************************************/
571 /*                     MP4 Header Check API                            */
572 /***********************************************************************/
573 EXPORT_API
574 int MMFileFormatIsValidMP4 (const char *mmfileuri)
575 {
576 #define _MMFILE_MP4_HEADER_LENGTH 4
577 #define _MMFILE_MP4_CHECK_LIMIT         (1024*10)       /*10Kbyte*/
578         MMFileIOHandle *fp = NULL;
579         unsigned char buffer[_MMFILE_MP4_HEADER_LENGTH] = {0,};
580         long long     filesize = 0;
581         int           readed = 0;
582         unsigned int  startoffset = 0;
583         int ret = 0;
584         unsigned int check_limit = 0;
585
586         if (NULL == mmfileuri) {
587                 debug_error ("file source is NULL\n");
588                 return ret;
589         }
590
591         ret = mmfile_open (&fp, mmfileuri, MMFILE_RDONLY);
592         if (ret == MMFILE_UTIL_FAIL) {
593                 debug_error ("error: mmfile_open\n");
594                 goto exit;
595         }
596
597         /* Initialize the members of handle */
598         mmfile_seek (fp, 0, MMFILE_SEEK_END);
599         filesize = mmfile_tell(fp);
600         mmfile_seek (fp, 0, MMFILE_SEEK_SET);
601
602         if (filesize < _MMFILE_MP4_HEADER_LENGTH) {
603                 debug_error ( "header is too small.\n");
604                 ret = 0;
605                 goto exit;
606         }
607
608         ret = 0;
609
610         /**@note weak check*/
611         check_limit = (filesize > _MMFILE_MP4_CHECK_LIMIT) ? _MMFILE_MP4_CHECK_LIMIT: filesize;
612         for (startoffset = 0; check_limit - (startoffset + _MMFILE_MP4_HEADER_LENGTH) > 0; startoffset++) {
613                 mmfile_seek (fp, startoffset, MMFILE_SEEK_SET);
614
615                 readed = mmfile_read (fp, buffer, _MMFILE_MP4_HEADER_LENGTH);
616                 if (readed != _MMFILE_MP4_HEADER_LENGTH) {
617                         debug_error ( "read error. size = %d. Maybe end of file.\n", readed);
618                         ret = 0;
619                         goto exit;
620                 }
621
622                 /*input is 4byte*/
623                 if (1 == _MMFileIsMP4Header (buffer)) {
624                         #ifdef __MMFILE_TEST_MODE__
625                         debug_msg ("MP4 Header Detected\n");
626                         #endif
627                         ret = 1;
628                         goto exit;
629                 }
630         }
631
632 exit:
633         if (fp) {
634                 mmfile_close (fp);
635         }
636
637         return ret;
638 }
639
640
641 /***********************************************************************/
642 /*                     AVI Header Check API                            */
643 /***********************************************************************/
644 EXPORT_API
645 int MMFileFormatIsValidAVI (const char *mmfileuri)
646 {
647 #define _MMFILE_AVI_HEADER_LENGTH 12
648
649         MMFileIOHandle *fp = NULL;
650         unsigned char buffer[_MMFILE_AVI_HEADER_LENGTH] = {0,};
651         long long     filesize = 0;
652         int           readed = 0;
653         unsigned int  startoffset = 0;
654         int ret = 0;
655
656         if (NULL == mmfileuri) {
657                 debug_error ("file source is NULL\n");
658                 return ret;
659         }
660
661         ret = mmfile_open (&fp, mmfileuri, MMFILE_RDONLY);
662         if (ret == MMFILE_UTIL_FAIL) {
663                 debug_error ("error: mmfile_open\n");
664                 goto exit;
665         }
666
667          /* Initialize the members of handle */
668         mmfile_seek (fp, 0, MMFILE_SEEK_END);
669         filesize = mmfile_tell(fp);
670         mmfile_seek (fp, 0, MMFILE_SEEK_SET);
671
672         if (filesize < _MMFILE_AVI_HEADER_LENGTH) {
673                 debug_error ( "header is too small.\n");
674                 ret = 0;
675                 goto exit;
676         }
677
678         ret = 0;        
679         startoffset = 0;
680
681         mmfile_seek (fp, startoffset, MMFILE_SEEK_SET);    
682
683         readed = mmfile_read (fp, buffer, _MMFILE_AVI_HEADER_LENGTH);
684         if (_MMFILE_AVI_HEADER_LENGTH != readed) {
685                 debug_error ( "read error. size = %d. Maybe end of file.\n", readed);
686                 ret = 0;
687                 goto exit;
688         }
689
690         if (1 == _MMFileIsAVIHeader (buffer)) {
691                 #ifdef __MMFILE_TEST_MODE__
692                 debug_msg ( "Header Detected \n");
693                 #endif
694                 ret = 1;
695                 goto exit;
696         }
697
698 exit:
699         if (fp) {
700                 mmfile_close (fp);
701         }
702
703         return ret;
704 }
705
706
707
708 /***********************************************************************/
709 /*                     ASF Header Check API                            */
710 /***********************************************************************/
711 EXPORT_API
712 int MMFileFormatIsValidASF (const char *mmfileuri)
713 {
714 #define _MMFILE_ASF_HEADER_LENGTH 16
715         MMFileIOHandle *fp = NULL;
716         unsigned char buffer[_MMFILE_ASF_HEADER_LENGTH] = {0,};
717         long long     filesize = 0;
718         int           readed = 0;
719         unsigned int  startoffset = 0;
720         int ret = 0;
721
722         if (NULL == mmfileuri) {
723                 debug_error ("file source is NULL\n");
724                 return ret;
725         }
726
727         ret = mmfile_open (&fp, mmfileuri, MMFILE_RDONLY);
728         if (ret == MMFILE_UTIL_FAIL) {
729                 debug_error ("error: mmfile_open\n");
730                 goto exit;
731         }
732
733         /* Initialize the members of handle */
734         mmfile_seek (fp, 0, MMFILE_SEEK_END);
735         filesize = mmfile_tell(fp);
736         mmfile_seek (fp, 0, MMFILE_SEEK_SET);
737
738         if (filesize < _MMFILE_ASF_HEADER_LENGTH) {
739                 debug_error ( "header is too small.\n");
740                 ret = 0;
741                 goto exit;
742         }
743
744         ret = 0;
745         startoffset = 0;
746
747         mmfile_seek (fp, startoffset, MMFILE_SEEK_SET);        
748
749         readed = mmfile_read (fp, buffer, _MMFILE_ASF_HEADER_LENGTH);
750         if (_MMFILE_ASF_HEADER_LENGTH != readed) {
751                 debug_error ( "read error. size = %d. Maybe end of file.\n", readed);
752                 ret = 0;
753                 goto exit;
754         }
755
756         if (1 == _MMFileIsASFHeader (buffer)) {
757                 #ifdef __MMFILE_TEST_MODE__
758                 debug_msg ( "Header Detected\n");
759                 #endif
760                 ret = 1;
761                 goto exit;
762         }
763
764 exit:
765         if (fp) {
766                 mmfile_close (fp);
767         }
768
769         return ret;
770 }
771
772 /***********************************************************************/
773 /*                     WMA Header Check API                            */
774 /***********************************************************************/
775 EXPORT_API
776 int MMFileFormatIsValidWMA (const char *mmfileuri)
777 {
778 #define _MMFILE_ASF_HEADER_LENGTH 16
779         MMFileIOHandle *fp = NULL;
780         unsigned char buffer[_MMFILE_ASF_HEADER_LENGTH] = {0,};
781         long long     filesize = 0;
782         int           readed = 0;
783         unsigned int  startoffset = 0;
784         int ret = 0;
785
786         if (NULL == mmfileuri) {
787                 debug_error ("file source is NULL\n");
788                 return ret;
789         }
790
791         ret = mmfile_open (&fp, mmfileuri, MMFILE_RDONLY);
792         if (ret == MMFILE_UTIL_FAIL) {
793                 debug_error ("error: mmfile_open\n");
794                 goto exit;
795         }
796
797         /* Initialize the members of handle */
798         mmfile_seek (fp, 0, MMFILE_SEEK_END);
799         filesize = mmfile_tell(fp);
800         mmfile_seek (fp, 0, MMFILE_SEEK_SET);
801
802         if (filesize < _MMFILE_ASF_HEADER_LENGTH) {
803                 debug_error ( "header is too small.\n");
804                 ret = 0;
805                 goto exit;
806         }
807
808         ret = 0;
809         startoffset = 0;
810
811         mmfile_seek (fp, startoffset, MMFILE_SEEK_SET);        
812
813         readed = mmfile_read (fp, buffer, _MMFILE_ASF_HEADER_LENGTH);
814         if (_MMFILE_ASF_HEADER_LENGTH != readed) {
815                 debug_error ( "read error. size = %d. Maybe end of file.\n", readed);
816                 ret = 0;
817                 goto exit;
818         }
819
820         if (1 == _MMFileIsASFHeader (buffer)) {
821                 #ifdef __MMFILE_TEST_MODE__
822                 debug_msg ( "Header Detected\n");
823                 #endif
824                 ret = 1;
825                 goto exit;
826         }
827
828 exit:
829         if (fp) {
830                 mmfile_close (fp);
831         }
832
833         return ret;
834 }
835
836
837
838 /***********************************************************************/
839 /*                     WMV Header Check API                            */
840 /***********************************************************************/
841 EXPORT_API
842 int MMFileFormatIsValidWMV (const char *mmfileuri)
843 {
844  #define _MMFILE_ASF_HEADER_LENGTH 16
845         MMFileIOHandle *fp = NULL;
846         unsigned char buffer[_MMFILE_ASF_HEADER_LENGTH] = {0,};
847         long long     filesize = 0;
848         int           readed = 0;
849         unsigned int  startoffset = 0;
850         int ret = 0;
851
852         if (NULL == mmfileuri) {
853                 debug_error ("file source is NULL\n");
854                 return ret;
855         }
856
857         ret = mmfile_open (&fp, mmfileuri, MMFILE_RDONLY);
858         if (ret == MMFILE_UTIL_FAIL) {
859                 debug_error ("error: mmfile_open\n");
860                 goto exit;
861         }
862
863         /* Initialize the members of handle */
864         mmfile_seek (fp, 0, MMFILE_SEEK_END);
865         filesize = mmfile_tell(fp);
866         mmfile_seek (fp, 0, MMFILE_SEEK_SET);
867
868         if (filesize < _MMFILE_ASF_HEADER_LENGTH) {
869                 debug_error ( "header is too small.\n");
870                 ret = 0;
871                 goto exit;
872         }
873
874         ret = 0;
875         startoffset = 0;
876
877         mmfile_seek (fp, startoffset, MMFILE_SEEK_SET);        
878
879         readed = mmfile_read (fp, buffer, _MMFILE_ASF_HEADER_LENGTH);
880         if (_MMFILE_ASF_HEADER_LENGTH != readed) {
881                 debug_error ( "read error. size = %d. Maybe end of file.\n", readed);
882                 ret = 0;
883                 goto exit;
884         }
885
886         if (1 == _MMFileIsASFHeader (buffer)) {
887                 #ifdef __MMFILE_TEST_MODE__
888                 debug_msg ( "Header Detected\n");
889                 #endif
890                 ret = 1;
891                 goto exit;
892         }
893
894 exit:
895         if (fp) {
896                 mmfile_close (fp);
897         }
898
899         return ret;
900 }
901
902
903 /***********************************************************************/
904 /*                     MMF Header Check API                            */
905 /***********************************************************************/
906 EXPORT_API
907 int MMFileFormatIsValidMMF (const char *mmfileuri)
908 {
909 #define _MMFILE_MMF_HEADER_LENGTH 18
910
911         MMFileIOHandle *fp = NULL;
912         unsigned char buffer[_MMFILE_MMF_HEADER_LENGTH] = {0,};
913         long long     filesize = 0;
914         int           readed = 0;
915         unsigned int  startoffset = 0;
916         int ret = 0;
917
918         if (NULL == mmfileuri) {
919                 debug_error ("file source is NULL\n");
920                 return ret;
921         }
922
923         ret = mmfile_open (&fp, mmfileuri, MMFILE_RDONLY);
924         if (ret == MMFILE_UTIL_FAIL) {
925                 debug_error ("error: mmfile_open\n");
926                 goto exit;
927         }
928
929         /* Initialize the members of handle */
930         mmfile_seek (fp, 0, MMFILE_SEEK_END);
931         filesize = mmfile_tell(fp);
932         mmfile_seek (fp, 0, MMFILE_SEEK_SET);
933
934         if (filesize < _MMFILE_MMF_HEADER_LENGTH) {
935                 debug_error ( "header is too small.\n");
936                 ret = 0;
937                 goto exit;
938         }
939
940         ret = 0;
941         startoffset = 0;
942
943         mmfile_seek (fp, startoffset, MMFILE_SEEK_SET);    
944
945         readed = mmfile_read (fp, buffer, _MMFILE_MMF_HEADER_LENGTH);
946         if (_MMFILE_MMF_HEADER_LENGTH != readed) {
947                 debug_error ( "read error. size = %d. Maybe end of file.\n", readed);
948                 ret = 0;
949                 goto exit;
950         }
951
952         if (1 == _MMFileIsMMFHeader (buffer)) {
953                 #ifdef __MMFILE_TEST_MODE__
954                 debug_msg ( "Header Detected\n");
955                 #endif
956                 ret = 1;
957                 goto exit;
958         }
959
960 exit:
961         if (fp) {
962                 mmfile_close (fp);
963         }
964
965         return ret;
966 }
967
968
969
970 /***********************************************************************/
971 /*                     MMF Header Check API                            */
972 /***********************************************************************/
973 EXPORT_API
974 int MMFileFormatIsValidIMY (const char *mmfileuri)
975 {
976 #define _MMFILE_IMY_HEADER_LENGTH 13
977
978         MMFileIOHandle *fp = NULL;
979         unsigned char buffer[_MMFILE_IMY_HEADER_LENGTH] = {0,};
980         long long     filesize = 0;
981         int           readed = 0;
982         unsigned int  startoffset = 0;
983         int ret = 0;
984
985         if (NULL == mmfileuri) {
986                 debug_error ("file source is NULL\n");
987                 return ret;
988         }
989
990         ret = mmfile_open (&fp, mmfileuri, MMFILE_RDONLY);
991         if (ret == MMFILE_UTIL_FAIL) {
992                 debug_error ("error: mmfile_open\n");
993                 goto exit;
994         }
995
996          /* Initialize the members of handle */
997         mmfile_seek (fp, 0, MMFILE_SEEK_END);
998         filesize = mmfile_tell(fp);
999         mmfile_seek (fp, 0, MMFILE_SEEK_SET);
1000
1001         if (filesize < _MMFILE_IMY_HEADER_LENGTH) {
1002                 debug_error ( "header is too small.\n");
1003                 ret = 0;
1004                 goto exit;
1005         }
1006
1007         ret = 0;
1008         startoffset = 0;
1009
1010         mmfile_seek (fp, startoffset, MMFILE_SEEK_SET);    
1011
1012         readed = mmfile_read (fp, buffer, _MMFILE_IMY_HEADER_LENGTH);
1013         if (_MMFILE_IMY_HEADER_LENGTH != readed) {
1014                 debug_error ( "read error. size = %d. Maybe end of file.\n", readed);
1015                 ret = 0;
1016                 goto exit;
1017         }
1018
1019         if (1 == _MMFileIsIMYHeader (buffer)) {
1020                 #ifdef __MMFILE_TEST_MODE__
1021                 debug_msg ( "Header Detected\n");
1022                 #endif
1023                 ret = 1;
1024                 goto exit;
1025         }
1026
1027 exit:
1028         if (fp) {
1029                 mmfile_close (fp);
1030         }
1031
1032         return ret;
1033 }
1034
1035
1036
1037 /***********************************************************************/
1038 /*                     AMR Header Check API                            */
1039 /***********************************************************************/
1040 EXPORT_API
1041 int MMFileFormatIsValidAMR (const char *mmfileuri)
1042 {
1043 #define _MMFILE_AMR_MAX_HEADER_SIZE 15
1044 #define _MMFILE_AMR_MIN_HEADER_SIZE 6
1045
1046         MMFileIOHandle *fp = NULL;
1047         unsigned char buffer[_MMFILE_AMR_MAX_HEADER_SIZE] = {0,};
1048         long long     filesize = 0;
1049         int           readed = 0;
1050         unsigned int  startoffset = 0;
1051         int ret = 0;
1052
1053         if (NULL == mmfileuri) {
1054                 debug_error ("file source is NULL\n");
1055                 return ret;
1056         }
1057
1058         ret = mmfile_open (&fp, mmfileuri, MMFILE_RDONLY);
1059         if (ret == MMFILE_UTIL_FAIL) {
1060                 debug_error ("error: mmfile_open\n");
1061                 goto exit;
1062         }
1063
1064         /* Initialize the members of handle */
1065         mmfile_seek (fp, 0, MMFILE_SEEK_END);
1066         filesize = mmfile_tell(fp);
1067         mmfile_seek (fp, 0, MMFILE_SEEK_SET);
1068
1069         if (filesize < _MMFILE_AMR_MAX_HEADER_SIZE) {
1070                 debug_error ("header is too small.\n");
1071                 ret = 0;
1072                 goto exit;
1073         }
1074
1075         ret = 0;
1076         startoffset = 0;
1077
1078         mmfile_seek (fp, startoffset, MMFILE_SEEK_SET);        
1079
1080         readed = mmfile_read (fp, buffer, _MMFILE_AMR_MAX_HEADER_SIZE);
1081         if (_MMFILE_AMR_MAX_HEADER_SIZE != readed) {
1082                 debug_error ("read error. size = %d. Maybe end of file.\n", readed);
1083                 ret = 0;
1084                 goto exit;
1085         }
1086
1087         if (1 == _MMFileIsAMRHeader (buffer)) {
1088                 #ifdef __MMFILE_TEST_MODE__
1089                 debug_msg ( "Header Detected\n");
1090                 #endif
1091                 ret = 1;
1092                 goto exit;
1093         }
1094
1095 exit:
1096         if (fp) {
1097                 mmfile_close (fp);
1098         }
1099
1100         return ret;
1101 }
1102
1103 /***********************************************************************/
1104 /*                     Matroska Header Check API                       */
1105 /***********************************************************************/
1106
1107 EXPORT_API
1108 int MMFileFormatIsValidMatroska (const char *mmfileuri)
1109 {
1110 #define _MMFILE_EBML_MARKER_LENGTH      4
1111
1112         MMFileIOHandle *fp = NULL;
1113         unsigned char* buffer = NULL;
1114         long long     filesize = 0;
1115         int           readed = 0;
1116         unsigned int  startoffset = 0;
1117         int ret = 0;
1118
1119         int len_mask = 0x80, size = 1, n = 1, total = 0;
1120         char probe_data[] = { 'm', 'a', 't', 'r', 'o', 's', 'k', 'a' };
1121
1122         if (NULL == mmfileuri) {
1123                 debug_error ("file source is NULL\n");
1124                 return ret;
1125         }
1126
1127         debug_msg ( "[%s][%d]\n", __func__, __LINE__);
1128         ret = mmfile_open (&fp, mmfileuri, MMFILE_RDONLY);
1129         if (ret == MMFILE_UTIL_FAIL) {
1130                 debug_error ("error: mmfile_open\n");
1131                 goto exit;
1132         }
1133
1134          /* Initialize the members of handle */
1135         mmfile_seek (fp, 0, MMFILE_SEEK_END);
1136         filesize = mmfile_tell(fp);
1137         mmfile_seek (fp, 0, MMFILE_SEEK_SET);
1138
1139         ret = 0;
1140
1141         /* set begin and end point at the file */
1142         startoffset = 0;
1143
1144         mmfile_seek (fp, startoffset, MMFILE_SEEK_SET);
1145
1146         buffer = mmfile_malloc (_MMFILE_EBML_MARKER_LENGTH * sizeof(char));
1147         readed = mmfile_read (fp, buffer, _MMFILE_EBML_MARKER_LENGTH);
1148         if (_MMFILE_EBML_MARKER_LENGTH != readed) {
1149                 debug_error ( "read error. size = %d. Maybe end of file.\n", readed);
1150                 ret = 0;
1151                 goto exit;
1152         }
1153
1154         /* ebml header? */
1155           if (buffer[0] != 0x1A || buffer[1] != 0x45 || buffer[2] != 0xDF || buffer[3] != 0xA3) {
1156                 debug_msg ("This is not a EBML format\n");
1157             ret = 0;
1158             goto exit;
1159           }
1160
1161           /* length of header */
1162             mmfile_read (fp, (unsigned char*)(&total), 1);
1163             debug_msg ("Initial total header size = [0x%x]\n", total);
1164
1165             while (size <= 8 && !(total & len_mask)) {
1166               debug_error ("This case can not be handled yet....")
1167               size++;
1168               len_mask >>= 1;
1169             }
1170             if (size > 8) {
1171                 debug_error ("This case can not be handled yet....")
1172                 ret = 0;
1173                 goto exit;
1174             }
1175             total &= (len_mask - 1);
1176             while (n < size) {
1177               debug_error ("This case can not be handled yet....")
1178               ret = 0;
1179               goto exit;
1180             }
1181
1182             debug_msg ("Final total header size = [%d]\n", total);
1183
1184             if (buffer)
1185                 mmfile_free (buffer);
1186             buffer = mmfile_malloc (total * sizeof(char));
1187             mmfile_read (fp, buffer, total);
1188
1189             for (n = 0; n <= total - sizeof (probe_data); n++) {
1190               if (!memcmp (&buffer[n], probe_data, sizeof (probe_data))) {
1191                 debug_msg ("String matroska found!!!\n");
1192                 ret = 1;
1193                 goto exit;
1194               }
1195             }
1196
1197 exit:
1198         if (buffer) {
1199                 mmfile_free (buffer);
1200         }
1201
1202         if (fp) {
1203                 mmfile_close (fp);
1204         }
1205
1206         return ret;
1207 }
1208
1209 /***********************************************************************/
1210 /*                     QT Header Check API                       */
1211 /***********************************************************************/
1212 EXPORT_API
1213 int MMFileFormatIsValidQT (const char *mmfileuri)
1214 {
1215         return 1;
1216 }
1217
1218 /***********************************************************************/
1219 /*                     Flac Header Check API                       */
1220 /***********************************************************************/
1221 EXPORT_API
1222 int MMFileFormatIsValidFLAC (const char *mmfileuri)
1223 {
1224 #define _MMFILE_FLAC_HEADER_LENGTH 5    /*fLaC*/
1225
1226         MMFileIOHandle *fp = NULL;
1227         unsigned char buffer[_MMFILE_FLAC_HEADER_LENGTH] = {0,};
1228         long long         filesize = 0;
1229         int               readed = 0;
1230         unsigned int  startoffset = 0;
1231         int ret = 0;
1232
1233         if (NULL == mmfileuri) {
1234                 debug_error ("file source is NULL\n");
1235                 return ret;
1236         }
1237
1238         ret = mmfile_open (&fp, mmfileuri, MMFILE_RDONLY);
1239         if (ret == MMFILE_UTIL_FAIL) {
1240                 debug_error ("error: mmfile_open\n");
1241                 goto exit;
1242         }
1243
1244         /* Initialize the members of handle */
1245         mmfile_seek (fp, 0, MMFILE_SEEK_END);
1246         filesize = mmfile_tell(fp);
1247         mmfile_seek (fp, 0, MMFILE_SEEK_SET);
1248
1249         if (filesize < _MMFILE_FLAC_HEADER_LENGTH) {
1250                 debug_error ( "header is too small.\n");
1251                 ret = 0;
1252                 goto exit;
1253         }
1254
1255         ret = 0;
1256
1257         /* set begin and end point at the file */
1258         startoffset = 0;
1259
1260         mmfile_seek (fp, startoffset, MMFILE_SEEK_SET);
1261
1262         readed = mmfile_read (fp, buffer, _MMFILE_FLAC_HEADER_LENGTH);
1263         if (_MMFILE_FLAC_HEADER_LENGTH != readed) {
1264                 debug_error ( "read error. size = %d. Maybe end of file.\n", readed);
1265                 ret = 0;
1266                 goto exit;
1267         }
1268
1269         if (1 == _MMFileIsFLACHeader (buffer)) {
1270 #ifdef __MMFILE_TEST_MODE__
1271                 debug_msg ( "Header Detected\n");
1272 #endif
1273                 ret = 1;
1274                 goto exit;
1275         }
1276
1277
1278 exit:
1279         if (fp) {
1280                 mmfile_close (fp);
1281         }
1282
1283 return ret;
1284 }
1285
1286 /***********************************************************************/
1287 /*                     FLV(flash video) Header Check API                       */
1288 /***********************************************************************/
1289 EXPORT_API
1290 int MMFileFormatIsValidFLV (const char *mmfileuri)
1291 {
1292 #define _MMFILE_FLV_HEADER_LENGTH 4     /*FLV*/
1293
1294         MMFileIOHandle *fp = NULL;
1295         unsigned char buffer[_MMFILE_FLV_HEADER_LENGTH] = {0,};
1296         long long         filesize = 0;
1297         int               readed = 0;
1298         unsigned int  startoffset = 0;
1299         int ret = 0;
1300
1301         if (NULL == mmfileuri) {
1302                 debug_error ("file source is NULL\n");
1303                 return ret;
1304         }
1305
1306         ret = mmfile_open (&fp, mmfileuri, MMFILE_RDONLY);
1307         if (ret == MMFILE_UTIL_FAIL) {
1308                 debug_error ("error: mmfile_open\n");
1309                 goto exit;
1310         }
1311
1312         /* Initialize the members of handle */
1313         mmfile_seek (fp, 0, MMFILE_SEEK_END);
1314         filesize = mmfile_tell(fp);
1315         mmfile_seek (fp, 0, MMFILE_SEEK_SET);
1316
1317         if (filesize < _MMFILE_FLV_HEADER_LENGTH) {
1318                 debug_error ( "header is too small.\n");
1319                 ret = 0;
1320                 goto exit;
1321         }
1322
1323         ret = 0;
1324
1325         /* set begin and end point at the file */
1326         startoffset = 0;
1327
1328         mmfile_seek (fp, startoffset, MMFILE_SEEK_SET);
1329
1330         readed = mmfile_read (fp, buffer, _MMFILE_FLV_HEADER_LENGTH);
1331         if (_MMFILE_FLV_HEADER_LENGTH != readed) {
1332                 debug_error ( "read error. size = %d. Maybe end of file.\n", readed);
1333                 ret = 0;
1334                 goto exit;
1335         }
1336
1337         if (1 == _MMFileIsFLVHeader (buffer)) {
1338 #ifdef __MMFILE_TEST_MODE__
1339                 debug_msg ( "Header Detected\n");
1340 #endif
1341                 ret = 1;
1342                 goto exit;
1343         }
1344
1345
1346 exit:
1347         if (fp) {
1348                 mmfile_close (fp);
1349         }
1350
1351 return ret;
1352 }
1353
1354 /***********************************************************************/
1355 /*            Implementation of Internal Functions                     */
1356 /***********************************************************************/
1357 static int _MMFileIsASFHeader  (void *header)
1358 {
1359         /* ID: 30 26 B2 75 8E 66 CF 11 A6 D9 00 AA 00 62 CE 6C */    
1360         unsigned char *s = header;
1361
1362         if ( (*(s +  0) == 0x30) &&
1363                  (*(s +  1) == 0x26) &&
1364                  (*(s +  2) == 0xB2) &&
1365                  (*(s +  3) == 0x75) &&
1366                  (*(s +  4) == 0x8E) &&
1367                  (*(s +  5) == 0x66) &&
1368                  (*(s +  6) == 0xCF) &&
1369                  (*(s +  7) == 0x11) &&
1370                  (*(s +  8) == 0xA6) &&
1371                  (*(s +  9) == 0xD9) &&
1372                  (*(s + 10) == 0x00) &&
1373                  (*(s + 11) == 0xAA) &&
1374                  (*(s + 12) == 0x00) &&
1375                  (*(s + 13) == 0x62) &&
1376                  (*(s + 14) == 0xCE) &&
1377                  (*(s + 15) == 0x6C) ) {
1378
1379                 return 1;
1380         }
1381
1382         return 0;
1383 }
1384
1385 static int _MMFileIsAMRHeader  (void *header)
1386 {
1387 #define _MMFILE_AMR_SINGLE_CH_HEADER_SIZE       6
1388 #define _MMFILE_AMR_SINGLE_CH_HEADER            "#!AMR\n"
1389
1390 #define _MMFILE_AMR_WB_SINGLE_CH_HEADER_SIZE    9
1391 #define _MMFILE_AMR_WB_SINGLE_CH_HEADER         "#!AMR-WB\n"
1392
1393 #define _MMFILE_AMR_MULTI_CH_HEADER_SIZE        12
1394 #define _MMFILE_AMR_MULTI_CH_HEADER             "#!AMR_MC1.0\n"
1395
1396 #define _MMFILE_AMR_WB_MULTI_CH_HEADER_SIZE     15
1397 #define _MMFILE_AMR_WB_MULTI_CH_HEADER          "#!AMR-WB_MC1.0\n"
1398
1399         unsigned char *s = header;
1400
1401         if (!memcmp (s, _MMFILE_AMR_SINGLE_CH_HEADER,    _MMFILE_AMR_SINGLE_CH_HEADER_SIZE) ||        
1402                 !memcmp (s, _MMFILE_AMR_WB_SINGLE_CH_HEADER, _MMFILE_AMR_WB_SINGLE_CH_HEADER_SIZE) ||
1403                 !memcmp (s, _MMFILE_AMR_MULTI_CH_HEADER,     _MMFILE_AMR_MULTI_CH_HEADER_SIZE) ||
1404                 !memcmp (s, _MMFILE_AMR_WB_MULTI_CH_HEADER,  _MMFILE_AMR_WB_MULTI_CH_HEADER_SIZE)) {
1405
1406                 return 1;
1407         }
1408
1409         return 0;
1410 }
1411
1412 static int _MMFileIsIMYHeader  (void *header)
1413 {
1414         unsigned char *s = header;
1415
1416         if (!memcmp(s, "BEGIN:IMELODY", 13)) {
1417                 return 1;
1418         }
1419
1420         return 0;
1421 }
1422
1423 static int _MMFileIsMIDHeader (void *header)
1424 {
1425         unsigned char *s = header;
1426
1427         if (!memcmp(s, "MThd", 4)) {    /*general MIDI*/
1428                 return 1;
1429         } else if (!memcmp (s, "XMF_", 4)) {    /*XMF*/
1430                 return 1;
1431         } else if (!memcmp(s, "IREZ", 4)) {
1432                 return 1;       /*RMF format*/
1433         }
1434
1435         return 0;
1436 }
1437
1438 static int _MMFileIsMMFHeader (void *header)
1439 {
1440 #define _MMFILE_MMF_TYPE_POSITION    ((char)0x11)
1441         unsigned char *s = header;
1442
1443         if(!memcmp (s, "MMMD", 4)) {
1444                 /* warning: comparison is always true due to limited range of data type */
1445                 if( *(s + _MMFILE_MMF_TYPE_POSITION) <= 0x2F ) {
1446                         return 1;
1447                 } else if (((*(s + _MMFILE_MMF_TYPE_POSITION) >= 0x30) && (*(s + _MMFILE_MMF_TYPE_POSITION) <= 0x38)) // MA3, MA5 type
1448                                  || ((*(s + _MMFILE_MMF_TYPE_POSITION) >= 0x40) && (*(s + _MMFILE_MMF_TYPE_POSITION) <= 0x48))
1449                                  || ((*(s + _MMFILE_MMF_TYPE_POSITION) >= 0x50) && (*(s + _MMFILE_MMF_TYPE_POSITION) <= 0x58))
1450                                  || ((*(s + _MMFILE_MMF_TYPE_POSITION) == 0xF0))) {
1451
1452                         return 1;
1453                 }
1454         }
1455
1456         return 0;
1457 }
1458
1459
1460 static int _MMFileIsAVIHeader (void *header)
1461 {
1462         unsigned char *s = header;
1463
1464         if (!memcmp(s, "RIFF", 4) && !memcmp(s+8, "AVI", 3)) {
1465                 return 1;
1466         }
1467
1468         return 0;
1469 }
1470
1471
1472 static int _MMFileIsWAVHeader (void *header)
1473 {
1474         unsigned char *s = header;
1475
1476         if (!memcmp(s, "RIFF", 4) && !memcmp(s+8, "WAVE", 4)) {
1477                 return 1;
1478         }
1479
1480         return 0;
1481 }
1482
1483
1484
1485 static int _MMFileIsMP4Header (void *header)
1486 {
1487         unsigned char *s = header;
1488
1489         if (!memcmp (s, "moov", 4) ||
1490                 !memcmp (s, "mdat", 4) ||
1491                 !memcmp (s, "ftyp", 4) ||
1492                 !memcmp (s, "free", 4) ||
1493                 !memcmp (s, "uuid", 4) ||
1494                 !memcmp (s, "skip", 4) ||
1495                 
1496                 !memcmp (s, "PICT", 4) ||
1497                 !memcmp (s, "wide", 4) ||
1498                 !memcmp (s, "prfl", 4)) {
1499                 return 1;
1500         }
1501
1502         return 0;
1503 }
1504
1505 static int _MMFileIsOGGHeader (void *header)
1506 {
1507         unsigned char *s = header;
1508
1509         if (!memcmp(s, "OggS", 4)) {
1510                 return 1;
1511         }
1512
1513         return 0;
1514 }
1515
1516 static int _MMFileIsMP3Header (void *header)
1517 {
1518         unsigned long head = 0;
1519         unsigned char *headc = header;
1520         unsigned int bitrate, layer, length, mode;
1521         unsigned int coef,samplerate, version, channels;
1522         static const unsigned int mp3types_bitrates[2][3][16] = {
1523                 {       {0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448,},
1524                         {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384,},
1525                         {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320,}},
1526                 {       {0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256,},
1527                         {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160,},
1528                         {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160,}},
1529         };
1530
1531         static const unsigned int mp3types_freqs[3][3] = {
1532                 {11025, 12000, 8000},
1533                 {22050, 24000, 16000},
1534                 {44100, 48000, 32000}
1535         };
1536
1537         static const unsigned int mp3FrameCoef[4][4] = {{-1,48,144,72},{-1,-1,-1,-1},{-1,48,144,72},{-1,48,144,144}};
1538
1539         /* header */
1540         head = (*(headc+0)<<24 | *(headc+1)<<16 | *(headc+2)<<8 | *(headc+3));
1541
1542         if ((head & 0xffe00000) != 0xffe00000) {
1543                  return 0;
1544         }
1545
1546         /* we don't need extension, copyright, original or
1547         * emphasis for the frame length */
1548         head >>= 6;
1549
1550         /* mode */
1551         mode = head & 0x3;
1552         head >>= 3;
1553
1554         /* padding */
1555         length = head & 0x1;
1556         head >>= 1;
1557
1558         /* sampling frequency */
1559         samplerate = head & 0x3;
1560         if (samplerate == 3) {
1561                 return 0;
1562         }
1563         head >>= 2;
1564
1565         /* bitrate index */
1566         bitrate = head & 0xF;
1567  
1568         if (bitrate == 15) {
1569                 return 0;
1570         }
1571
1572         /* ignore error correction, too */
1573         head >>= 5;
1574
1575         /* layer */
1576         layer = 4 - (head & 0x3);
1577         if (layer == 4) {
1578                 return 0;
1579         }
1580         head >>= 2;
1581
1582         /* version 0=MPEG2.5; 2=MPEG2; 3=MPEG1 */
1583         version = head & 0x3;
1584         if (version == 1) {
1585                 return 0;
1586         }
1587
1588         /* lookup */
1589         channels = (mode == 3) ? 1 : 2;
1590         samplerate = mp3types_freqs[version > 0 ? version - 1 : 0][samplerate];
1591         {
1592                 /* calculating */
1593                 bitrate = mp3types_bitrates[version == 3 ? 0 : 1][layer - 1][bitrate];
1594                 coef = mp3FrameCoef[version][layer];
1595                 if(layer == 1)
1596                         length = length*4;
1597
1598                 length = length + ((coef*bitrate*1000)/samplerate);
1599         }
1600
1601         return length;
1602 }
1603
1604 static int _MMFileSearchID3Tag (MMFileIOHandle *fp, unsigned int *offset)
1605 {
1606 #define _MMFILE_MP3_TAGV2_HEADER_LEN 10
1607 #define _MMFILE_GET_INT_NUMBER(buff) (int)( (((int)(buff)[0]) << 24) | (((int)(buff)[1]) << 16) | (((int)(buff)[2]) << 8) | (((int)(buff)[3])))
1608
1609         unsigned char tagHeader[_MMFILE_MP3_TAGV2_HEADER_LEN] = {0,};
1610         unsigned int tagInfoSize = 0;
1611         unsigned int acc_tagsize = 0;
1612         int tagVersion = 0;
1613         int encSize = 0;
1614         int readed = 0;
1615
1616         /*init offset*/
1617         *offset = 0;
1618
1619         mmfile_seek(fp, 0, MMFILE_SEEK_SET);
1620         
1621 _START_TAG_SEARCH:
1622
1623         readed = mmfile_read (fp, tagHeader, _MMFILE_MP3_TAGV2_HEADER_LEN);
1624         if (readed != _MMFILE_MP3_TAGV2_HEADER_LEN) {
1625                 debug_error ("read error occured.\n");
1626                 return 0;
1627         }
1628
1629         if (memcmp (tagHeader, "ID3", 3) == 0) {
1630                 #ifdef __MMFILE_TEST_MODE__
1631                 debug_msg ("'ID3' found.\n");
1632                 #endif
1633         } else {
1634                 #ifdef __MMFILE_TEST_MODE__
1635                 debug_msg ("'ID3' not found.\n");
1636                 #endif
1637                 goto search_end;
1638         }
1639
1640         /**@note weak id3v2 tag checking*/
1641         if (tagHeader[3] != 0xFF && tagHeader[4] != 0xFF &&
1642                 (tagHeader[6] & 0x80) == 0 && (tagHeader[7] & 0x80) == 0 &&
1643                 (tagHeader[8] & 0x80) == 0 && (tagHeader[9] & 0x80) == 0) {
1644                 #ifdef __MMFILE_TEST_MODE__
1645                 debug_msg ("good ID3V2 tag.\n");
1646                 #endif
1647         } else {
1648                 debug_warning ("It's bad ID3V2 tag.\n");
1649                 goto search_end;
1650         }
1651
1652         tagVersion = tagHeader[3];
1653
1654         if (tagVersion > 4) {
1655                 #ifdef __MMFILE_TEST_MODE__
1656                 debug_msg("Tag version not supported\n");
1657                 #endif
1658                 goto search_end;
1659         }
1660
1661         encSize = _MMFILE_GET_INT_NUMBER(&tagHeader[6]);
1662         tagInfoSize = _MMFILE_MP3_TAGV2_HEADER_LEN;
1663         tagInfoSize += (((encSize & 0x0000007F) >> 0) | ((encSize & 0x00007F00) >> 1) | ((encSize & 0x007F0000) >> 2) | ((encSize & 0x7F000000) >> 3));
1664
1665         /**@note unfortunately, some contents has many id3 tag.*/
1666         acc_tagsize += tagInfoSize;
1667         #ifdef __MMFILE_TEST_MODE__
1668         debug_msg("tag size: %u, offset: %u\n", tagInfoSize, acc_tagsize);
1669         #endif
1670
1671         mmfile_seek(fp, acc_tagsize, MMFILE_SEEK_SET);
1672         *offset = acc_tagsize;
1673         goto _START_TAG_SEARCH;
1674
1675 search_end:
1676         return 1;
1677 }
1678
1679 static int _MMFileIsFLACHeader  (void *header)
1680 {
1681         unsigned char *s = header;
1682
1683         if (!memcmp(s, "fLaC", 4)) {
1684                 return 1;
1685         }
1686
1687         return 0;
1688 }
1689
1690 static int _MMFileIsFLVHeader  (void *header)
1691 {
1692         unsigned char *s = header;
1693
1694         if (!memcmp(s, "FLV", 3)) {
1695                 return 1;
1696         }
1697
1698         return 0;
1699 }