Fix 64-bit build error
[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_file_debug.h"
25 #include "mm_file_utils.h"
26
27 /* Description of return value
28  * 0: false
29  * 1: true
30  */
31
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);
39
40 /***********************************************************************/
41 /*                     MP3 Header Check API                            */
42 /***********************************************************************/
43
44 int MMFileFormatIsValidMP3(MMFileIOHandle *pFileIO, const char *mmfileuri, int frameCnt)
45 {
46 #define _MMFILE_MP3_HEADER_LENGTH   4
47 #define _MMFILE_MP3_BUFFER_LENGTH   8200
48
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;
55         int endoffset = 0;
56         int frameSize = 0;
57         int ret = 0, count = 0, offset = 0;
58
59         if (fp == NULL)
60                 mm_file_retvm_if_fails(DEBUG, mmfile_open(&fp, mmfileuri, MMFILE_RDONLY) == MMFILE_UTIL_SUCCESS, MMFILE_UTIL_FAIL);
61
62         filesize = mmfile_get_size(fp);
63
64         if (filesize < _MMFILE_MP3_HEADER_LENGTH) {
65                 debug_error(DEBUG, "header is too small.");
66                 goto exit;
67         }
68
69         /* Search the existance of ID3 tag */
70         if (!_MMFileSearchID3Tag(fp, &sizeID3)) {
71                 debug_error(RELEASE, "Error in searching the ID3 tag");
72         /* goto exit; */
73         }
74
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;
80
81         /* find sync bit */
82         i = startoffset;
83         count = 0;
84
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");
90                         break;
91                 }
92
93                 offset = 1;
94                 for (j = 0; (j <= readn - _MMFILE_MP3_HEADER_LENGTH); j = j + offset) {
95                         frameSize = _MMFileIsMP3Header(buffer + j);
96
97                         offset = 1;
98
99                         if (frameSize) {
100
101                                 if ((j + frameSize) >= (endoffset - (i + _MMFILE_MP3_HEADER_LENGTH))) {
102                                         goto failMP3;
103                                 }
104
105                                 if ((j + frameSize) >= (readn - _MMFILE_MP3_HEADER_LENGTH)) {
106                                         debug_msg(RELEASE, "MP3 coner hit %d %d", j, frameSize);
107                                         break;
108                                 }
109
110                                 frameSize = _MMFileIsMP3Header(buffer + j + frameSize);
111
112                                 if (frameSize) {
113                                         offset = frameSize;
114                                         count++;
115                                         if (count == frameCnt) {
116                                                 ret = 1;
117                                                 debug_msg(RELEASE, "Header Detected at %d", i + j);
118                                                 goto exit;
119                                         }
120                                 } else {
121                                         offset = 1;
122                                 }
123                         }
124                 }
125
126                 /*If j is zero, this loop is infinite */
127                 if (j == 0) j++;
128
129                 i = i + j;
130         }
131
132 failMP3:
133         debug_msg(RELEASE, "Header Not Detected at: %d", i + j);
134  exit:
135         if (pFileIO == NULL && fp != NULL)
136                 mmfile_close(fp);
137
138         return ret;
139 }
140
141
142
143 /***********************************************************************/
144 /*                     AAC Header Check API                            */
145 /***********************************************************************/
146
147 int MMFileFormatIsValidAAC(MMFileIOHandle *pFileIO, const char *mmfileuri, int dummy)
148 {
149 #define _MMFILE_AAC_HEADER_LENGTH   4
150 #define _MMFILE_AAC_BUFFER_LENGTH   8200
151
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;
157         int ret = 0;
158         int startoffset = 0;
159         int endoffset = 0;
160         unsigned int sync = 0;
161         int frameSize = 0;
162
163         if (fp == NULL)
164                 mm_file_retvm_if_fails(DEBUG, mmfile_open(&fp, mmfileuri, MMFILE_RDONLY) == MMFILE_UTIL_SUCCESS, MMFILE_UTIL_FAIL);
165
166         filesize = mmfile_get_size(fp);
167
168         if (filesize < _MMFILE_AAC_HEADER_LENGTH) {
169                 debug_error(DEBUG, "header is too small.");
170                 goto exit;
171         }
172
173         /* Search the existance of ID3 tag */
174         if (!_MMFileSearchID3Tag(fp, &sizeID3)) {
175                 debug_error(RELEASE, "Error in searching the ID3 tag");
176         /* goto exit; */
177         }
178
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;
184
185         i = startoffset;
186
187         while (i < endoffset) {
188                 mmfile_seek(fp, i, MMFILE_SEEK_SET);
189
190                 readn = mmfile_read(fp, buffer, _MMFILE_AAC_BUFFER_LENGTH);
191
192                 if (readn < _MMFILE_AAC_HEADER_LENGTH) {
193                         debug_error(RELEASE, "read error");
194                         break;
195                 }
196
197                 debug_msg(RELEASE, "read error. size = %d. i = %d", readn, i);
198
199                 for (j = 0; (j < readn - _MMFILE_AAC_HEADER_LENGTH); j++) {
200
201                         sync = ((buffer[j] << 8) | (buffer[j + 1]));
202
203                         if ((sync & 0xFFF6) == 0xFFF0) {
204                                 frameSize = (((buffer[j + 3] & 0x03) << 11) | (buffer[j + 4] << 3) | ((buffer[j + 5] & 0xE0) >> 5));
205
206                                 if (frameSize == 0) {
207                                         continue;
208                                 }
209
210                                 if ((j + frameSize) >= (endoffset - (i + 2))) {
211                                         goto fail;
212                                 }
213                                 if ((j + frameSize) >= (readn - 2)) {
214                                         debug_msg(RELEASE, "AAC coner hit %d %d", j, frameSize);
215                                         break;
216                                 }
217
218                                 sync = ((buffer[j + frameSize] << 8) | (buffer[j + frameSize + 1]));
219
220                                 if ((sync & 0xFFF6) == 0xFFF0) {
221                                         ret = 1;
222                                         debug_msg(RELEASE, "AAC ADTS Header Detected at %d", i + j);
223                                         goto exit;
224                                 }
225                         } else if (!memcmp((buffer + j), "ADIF", 4)) {
226                                 ret = 1;
227                                 debug_msg(RELEASE, "AAC ADIF Header Detected at %d", i + j);
228                                 goto exit;
229                         }
230                 }
231                 /*If j is zero, this loop is infinite */
232                 if (j == 0) j++;
233
234                 i = i + j;
235         }
236
237
238 fail:
239         debug_msg(RELEASE, "Header Detected Failed");
240 exit:
241         if (pFileIO == NULL && fp != NULL)
242                 mmfile_close(fp);
243
244         return ret;
245 }
246
247
248
249 /***********************************************************************/
250 /*                     OGG Header Check API                            */
251 /***********************************************************************/
252
253 int MMFileFormatIsValidOGG(MMFileIOHandle *pFileIO, const char *mmfileuri, int dummy)
254 {
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)
258
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;
264         int startoffset = 0;
265         int endoffset = 0;
266         int ret = 0;
267         int check_limit = 0;
268
269         if (fp == NULL)
270                 mm_file_retvm_if_fails(DEBUG, mmfile_open(&fp, mmfileuri, MMFILE_RDONLY) == MMFILE_UTIL_SUCCESS, MMFILE_UTIL_FAIL);
271
272         filesize = mmfile_get_size(fp);
273
274         if (filesize < _MMFILE_OGG_HEADER_LENGTH) {
275                 debug_error(DEBUG, "header is too small.");
276                 goto exit;
277         }
278
279         /* Search the existance of ID3 tag */
280         if (!_MMFileSearchID3Tag(fp, &sizeID3)) {
281                 debug_error(RELEASE, "Error in searching the ID3 tag");
282         /* goto exit; */
283         }
284
285         /* set begin and end point at the file */
286         startoffset += sizeID3;
287         endoffset = filesize - _MMFILE_OGG_HEADER_LENGTH;
288
289         check_limit = (endoffset > _MMFILE_OGG_CHECK_LIMIT) ? _MMFILE_OGG_CHECK_LIMIT : endoffset;
290
291         i = startoffset;
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");
297                         break;
298                 }
299
300                 for (j = 0; (j <= readn - _MMFILE_OGG_HEADER_LENGTH); j++) {
301                         if (!memcmp(buffer + j, "OggS", 4)) {
302                                 ret = 1;
303                                 debug_msg(RELEASE, "Header Detected at %d", i + j);
304                                 goto exit;
305                         }
306                 }
307
308                 memset(buffer, 0x00, _MMFILE_OGG_BUFFER_LENGTH);
309
310                 i = i + j;
311         }
312
313 exit:
314         if (pFileIO == NULL && fp != NULL)
315                 mmfile_close(fp);
316
317         return ret;
318 }
319
320
321
322 /***********************************************************************/
323 /*                     MIDI Header Check API                           */
324 /***********************************************************************/
325
326 int MMFileFormatIsValidMID(MMFileIOHandle *pFileIO, const char *mmfileuri, int dummy)
327 {
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)
331
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;
336         int startoffset = 0;
337         int endoffset = 0;
338         int ret = 0;
339         int check_limit = 0;
340
341         if (fp == NULL)
342                 mm_file_retvm_if_fails(DEBUG, mmfile_open(&fp, mmfileuri, MMFILE_RDONLY) == MMFILE_UTIL_SUCCESS, MMFILE_UTIL_FAIL);
343
344         filesize = mmfile_get_size(fp);
345
346         if (filesize < _MMFILE_MIDI_HEADER_LENGTH) {
347                 debug_error(DEBUG, "header is too small.");
348                 goto exit;
349         }
350
351         /* set begin and end point at the file */
352         startoffset = 0;
353         endoffset = filesize - _MMFILE_MIDI_HEADER_LENGTH;
354
355         check_limit = (endoffset > _MMFILE_MIDI_CHECK_LIMIT) ? _MMFILE_MIDI_CHECK_LIMIT : endoffset;
356
357         i = startoffset;
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");
363                         break;
364                 }
365
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)) {
368                                 ret = 1;
369                                 debug_msg(RELEASE, "Header Detected at %d", i + j);
370                                 goto exit;
371                         }
372                 }
373
374                 memset(buffer, 0x00, _MMFILE_MIDI_BUFFER_LENGTH);
375
376                 i = i + j;
377         }
378
379 exit:
380         if (pFileIO == NULL && fp != NULL)
381                 mmfile_close(fp);
382
383         return ret;
384 }
385
386
387 /***********************************************************************/
388 /*                     WAV Header Check API                            */
389 /***********************************************************************/
390
391 int MMFileFormatIsValidWAV(MMFileIOHandle *pFileIO, const char *mmfileuri, int dummy)
392 {
393 #define _MMFILE_WAV_HEADER_LENGTH 15
394
395         MMFileIOHandle *fp = pFileIO;
396         unsigned char buffer[_MMFILE_WAV_HEADER_LENGTH] = {0, };
397         int ret = 0;
398
399         if (fp == NULL)
400                 mm_file_retvm_if_fails(DEBUG, mmfile_open(&fp, mmfileuri, MMFILE_RDONLY) == MMFILE_UTIL_SUCCESS, MMFILE_UTIL_FAIL);
401
402         mmfile_seek(fp, 0L, MMFILE_SEEK_SET);
403
404         if (mmfile_read(fp, buffer, _MMFILE_WAV_HEADER_LENGTH) != _MMFILE_WAV_HEADER_LENGTH) {
405                 debug_error(RELEASE, "read error");
406                 goto exit;
407         }
408
409         if (!memcmp(buffer, "RIFF", 4) && !memcmp(buffer + 8, "WAVE", 4)) {
410                 debug_msg(RELEASE, "Header Detected");
411                 ret = 1;
412         }
413
414 exit:
415         if (pFileIO == NULL && fp != NULL)
416                 mmfile_close(fp);
417
418         return ret;
419 }
420
421
422
423 /***********************************************************************/
424 /*                     MP4 Header Check API                            */
425 /***********************************************************************/
426
427 int MMFileFormatIsValidMP4(MMFileIOHandle *pFileIO, const char *mmfileuri, int dummy)
428 {
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;
435         int ret = 0;
436         unsigned int check_limit = 0;
437
438         if (fp == NULL)
439                 mm_file_retvm_if_fails(DEBUG, mmfile_open(&fp, mmfileuri, MMFILE_RDONLY) == MMFILE_UTIL_SUCCESS, MMFILE_UTIL_FAIL);
440
441         filesize = mmfile_get_size(fp);
442
443         if (filesize < _MMFILE_MP4_HEADER_LENGTH) {
444                 debug_error(DEBUG, "header is too small.");
445                 goto exit;
446         }
447
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);
452
453                 if (mmfile_read(fp, buffer, _MMFILE_MP4_HEADER_LENGTH) != _MMFILE_MP4_HEADER_LENGTH) {
454                         debug_error(RELEASE, "read error");
455                         goto exit;
456                 }
457
458                 /*input is 4byte*/
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");
463                         ret = 1;
464                         goto exit;
465                 }
466         }
467
468 exit:
469         if (pFileIO == NULL && fp != NULL)
470                 mmfile_close(fp);
471
472         return ret;
473 }
474
475
476 /***********************************************************************/
477 /*                     AVI Header Check API                            */
478 /***********************************************************************/
479
480 int MMFileFormatIsValidAVI(MMFileIOHandle *pFileIO, const char *mmfileuri, int dummy)
481 {
482 #define _MMFILE_AVI_HEADER_LENGTH 12
483
484         MMFileIOHandle *fp = pFileIO;
485         unsigned char buffer[_MMFILE_AVI_HEADER_LENGTH] = {0, };
486         int ret = 0;
487
488         if (fp == NULL)
489                 mm_file_retvm_if_fails(DEBUG, mmfile_open(&fp, mmfileuri, MMFILE_RDONLY) == MMFILE_UTIL_SUCCESS, MMFILE_UTIL_FAIL);
490
491         mmfile_seek(fp, 0L, MMFILE_SEEK_SET);
492
493         if (mmfile_read(fp, buffer, _MMFILE_AVI_HEADER_LENGTH) != _MMFILE_AVI_HEADER_LENGTH) {
494                 debug_error(RELEASE, "read error");
495                 goto exit;
496         }
497
498         if (!memcmp(buffer, "RIFF", 4) && !memcmp(buffer + 8, "AVI", 3)) {
499                 debug_msg(RELEASE, "Header Detected ");
500                 ret = 1;
501         }
502
503 exit:
504         if (pFileIO == NULL && fp != NULL)
505                 mmfile_close(fp);
506
507         return ret;
508 }
509
510
511
512 /***********************************************************************/
513 /*                     ASF Header Check API                            */
514 /***********************************************************************/
515
516 int MMFileFormatIsValidASF(MMFileIOHandle *pFileIO, const char *mmfileuri, int dummy)
517 {
518 #define _MMFILE_ASF_HEADER_LENGTH 16
519         MMFileIOHandle *fp = pFileIO;
520         unsigned char buffer[_MMFILE_ASF_HEADER_LENGTH] = {0, };
521         int ret = 0;
522
523         if (fp == NULL)
524                 mm_file_retvm_if_fails(DEBUG, mmfile_open(&fp, mmfileuri, MMFILE_RDONLY) == MMFILE_UTIL_SUCCESS, MMFILE_UTIL_FAIL);
525
526         mmfile_seek(fp, 0L, MMFILE_SEEK_SET);
527
528         if (mmfile_read(fp, buffer, _MMFILE_ASF_HEADER_LENGTH) != _MMFILE_ASF_HEADER_LENGTH) {
529                 debug_error(RELEASE, "read error");
530                 goto exit;
531         }
532
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");
539                 ret = 1;
540         }
541
542 exit:
543         if (pFileIO == NULL && fp != NULL)
544                 mmfile_close(fp);
545
546         return ret;
547 }
548
549 /***********************************************************************/
550 /*                     WMA Header Check API                            */
551 /***********************************************************************/
552
553 int MMFileFormatIsValidWMA(MMFileIOHandle *pFileIO, const char *mmfileuri, int dummy)
554 {
555         return MMFileFormatIsValidASF(pFileIO, mmfileuri, dummy);
556 }
557
558
559
560 /***********************************************************************/
561 /*                     WMV Header Check API                            */
562 /***********************************************************************/
563
564 int MMFileFormatIsValidWMV(MMFileIOHandle *pFileIO, const char *mmfileuri, int dummy)
565 {
566         return MMFileFormatIsValidASF(pFileIO, mmfileuri, dummy);
567 }
568
569
570 /***********************************************************************/
571 /*                     MMF Header Check API                            */
572 /***********************************************************************/
573
574 int MMFileFormatIsValidMMF(MMFileIOHandle *pFileIO, const char *mmfileuri, int dummy)
575 {
576 #define _MMFILE_MMF_HEADER_LENGTH 18
577
578         MMFileIOHandle *fp = pFileIO;
579         unsigned char buffer[_MMFILE_MMF_HEADER_LENGTH] = {0, };
580         int ret = 0;
581
582         if (fp == NULL)
583                 mm_file_retvm_if_fails(DEBUG, mmfile_open(&fp, mmfileuri, MMFILE_RDONLY) == MMFILE_UTIL_SUCCESS, MMFILE_UTIL_FAIL);
584
585         mmfile_seek(fp, 0L, MMFILE_SEEK_SET);
586
587         if (mmfile_read(fp, buffer, _MMFILE_MMF_HEADER_LENGTH) != _MMFILE_MMF_HEADER_LENGTH) {
588                 debug_error(RELEASE, "read error");
589                 goto exit;
590         }
591
592         if (_MMFileIsMMFHeader(buffer)) {
593                 debug_msg(RELEASE, "Header Detected");
594                 ret = 1;
595         }
596
597 exit:
598         if (pFileIO == NULL && fp != NULL)
599                 mmfile_close(fp);
600
601         return ret;
602 }
603
604
605
606 /***********************************************************************/
607 /*                     MMF Header Check API                            */
608 /***********************************************************************/
609
610 int MMFileFormatIsValidIMY(MMFileIOHandle *pFileIO, const char *mmfileuri, int dummy)
611 {
612 #define _MMFILE_IMY_HEADER_LENGTH 13
613
614         MMFileIOHandle *fp = pFileIO;
615         unsigned char buffer[_MMFILE_IMY_HEADER_LENGTH] = {0, };
616         int ret = 0;
617
618         if (fp == NULL)
619                 mm_file_retvm_if_fails(DEBUG, mmfile_open(&fp, mmfileuri, MMFILE_RDONLY) == MMFILE_UTIL_SUCCESS, MMFILE_UTIL_FAIL);
620
621         mmfile_seek(fp, 0L, MMFILE_SEEK_SET);
622
623         if (mmfile_read(fp, buffer, _MMFILE_IMY_HEADER_LENGTH) != _MMFILE_IMY_HEADER_LENGTH) {
624                 debug_error(RELEASE, "read error");
625                 goto exit;
626         }
627
628         if (!memcmp(buffer, "BEGIN:IMELODY", 13)) {
629                 debug_msg(RELEASE, "Header Detected");
630                 ret = 1;
631         }
632
633 exit:
634         if (pFileIO == NULL && fp != NULL)
635                 mmfile_close(fp);
636
637         return ret;
638 }
639
640
641
642 /***********************************************************************/
643 /*                     AMR Header Check API                            */
644 /***********************************************************************/
645
646 int MMFileFormatIsValidAMR(MMFileIOHandle *pFileIO, const char *mmfileuri, int dummy)
647 {
648 #define _MMFILE_AMR_MAX_HEADER_SIZE 15
649 #define _MMFILE_AMR_MIN_HEADER_SIZE 6
650
651         MMFileIOHandle *fp = pFileIO;
652         unsigned char buffer[_MMFILE_AMR_MAX_HEADER_SIZE] = {0, };
653         int ret = 0;
654
655         if (fp == NULL)
656                 mm_file_retvm_if_fails(DEBUG, mmfile_open(&fp, mmfileuri, MMFILE_RDONLY) == MMFILE_UTIL_SUCCESS, MMFILE_UTIL_FAIL);
657
658         mmfile_seek(fp, 0L, MMFILE_SEEK_SET);
659
660         if (mmfile_read(fp, buffer, _MMFILE_AMR_MAX_HEADER_SIZE) != _MMFILE_AMR_MAX_HEADER_SIZE) {
661                 debug_error(RELEASE, "read error");
662                 goto exit;
663         }
664
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");
670                 ret = 1;
671                 goto exit;
672         }
673
674 exit:
675         if (pFileIO == NULL && fp != NULL)
676                 mmfile_close(fp);
677
678         return ret;
679 }
680
681 /***********************************************************************/
682 /*                     Matroska Header Check API                       */
683 /***********************************************************************/
684
685 int MMFileFormatIsValidMatroska(MMFileIOHandle *pFileIO, const char *mmfileuri, int dummy)
686 {
687 #define _MMFILE_EBML_MARKER_LENGTH      4
688 #define _MMFILE_MKV_READ_BUFFER_LENGTH 2048
689
690         MMFileIOHandle *fp = pFileIO;
691         unsigned char buffer[_MMFILE_MKV_READ_BUFFER_LENGTH] = {0, };
692         int ret = 0;
693         int len_mask = 0x80;
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" };
698         if (fp == NULL)
699                 mm_file_retvm_if_fails(DEBUG, mmfile_open(&fp, mmfileuri, MMFILE_RDONLY) == MMFILE_UTIL_SUCCESS, MMFILE_UTIL_FAIL);
700
701         mmfile_seek(fp, 0L, MMFILE_SEEK_SET);
702
703         if (mmfile_read(fp, buffer, _MMFILE_MKV_READ_BUFFER_LENGTH) != _MMFILE_MKV_READ_BUFFER_LENGTH) {
704                 debug_error(RELEASE, "read error");
705                 goto exit;
706         }
707
708         /* ebml header? */
709         if (buffer[0] != 0x1A || buffer[1] != 0x45 || buffer[2] != 0xDF || buffer[3] != 0xA3) {
710                 debug_msg(RELEASE, "This is not a EBML format");
711                 goto exit;
712         }
713
714         /* length of header */
715         total = buffer[4];
716
717         debug_msg(RELEASE, "Initial total header size = [%lu]", total);
718
719         while (size <= 8 && !(total & len_mask)) {
720                 debug_msg(DEBUG, "This case can not be handled yet....");
721                 size++;
722                 len_mask >>= 1;
723         }
724
725         debug_msg(RELEASE, "Final total header size = [%lu]", total);
726
727         if (size > 8) {
728                 debug_msg(DEBUG, "This case can not be handled yet....");
729                 goto exit;
730         }
731
732         total &= (len_mask - 1);
733
734         while (n < size) {
735                 total = (total << 8) | buffer[4 + n++];
736                 debug_msg(DEBUG, "This case can not be handled yet....");
737         }
738
739         /* Does the probe data contain the whole header? */
740         if (_MMFILE_MKV_READ_BUFFER_LENGTH < 4 + size + total)
741                 return 0;
742
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)
747                         continue;
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]);
751                                 ret = 1;
752                                 goto exit;
753                         }
754                 }
755         }
756
757 exit:
758         if (pFileIO == NULL && fp != NULL)
759                 mmfile_close(fp);
760
761         return ret;
762 }
763
764 /***********************************************************************/
765 /*                     QT Header Check API                       */
766 /***********************************************************************/
767
768 int MMFileFormatIsValidQT(MMFileIOHandle *pFileIO, const char *mmfileuri, int dummy)
769 {
770         return 1;
771 }
772
773 /***********************************************************************/
774 /*                     Flac Header Check API                       */
775 /***********************************************************************/
776
777 int MMFileFormatIsValidFLAC(MMFileIOHandle *pFileIO, const char *mmfileuri, int dummy)
778 {
779 #define _MMFILE_FLAC_HEADER_LENGTH 5    /*fLaC*/
780
781         MMFileIOHandle *fp = pFileIO;
782         unsigned char buffer[_MMFILE_FLAC_HEADER_LENGTH] = {0, };
783         int ret = 0;
784
785         if (fp == NULL)
786                 mm_file_retvm_if_fails(DEBUG, mmfile_open(&fp, mmfileuri, MMFILE_RDONLY) == MMFILE_UTIL_SUCCESS, MMFILE_UTIL_FAIL);
787
788         mmfile_seek(fp, 0L, MMFILE_SEEK_SET);
789
790         if (mmfile_read(fp, buffer, _MMFILE_FLAC_HEADER_LENGTH) != _MMFILE_FLAC_HEADER_LENGTH) {
791                 debug_error(RELEASE, "read error");
792                 goto exit;
793         }
794
795         if (!memcmp(buffer, "fLaC", 4)) {
796                 debug_msg(RELEASE, "Header Detected");
797                 ret = 1;
798         }
799
800 exit:
801         if (pFileIO == NULL && fp != NULL)
802                 mmfile_close(fp);
803
804         return ret;
805 }
806
807 /***********************************************************************/
808 /*                     FLV(flash video) Header Check API                       */
809 /***********************************************************************/
810
811 int MMFileFormatIsValidFLV(MMFileIOHandle *pFileIO, const char *mmfileuri, int dummy)
812 {
813 #define _MMFILE_FLV_HEADER_LENGTH 4     /*FLV*/
814
815         MMFileIOHandle *fp = pFileIO;
816         unsigned char buffer[_MMFILE_FLV_HEADER_LENGTH] = {0, };
817         int ret = 0;
818
819         if (fp == NULL)
820                 mm_file_retvm_if_fails(DEBUG, mmfile_open(&fp, mmfileuri, MMFILE_RDONLY) == MMFILE_UTIL_SUCCESS, MMFILE_UTIL_FAIL);
821
822         mmfile_seek(fp, 0L, MMFILE_SEEK_SET);
823
824         if (mmfile_read(fp, buffer, _MMFILE_FLV_HEADER_LENGTH) != _MMFILE_FLV_HEADER_LENGTH) {
825                 debug_error(RELEASE, "read error");
826                 goto exit;
827         }
828
829         if (!memcmp(buffer, "FLV", 3)) {
830                 debug_msg(RELEASE, "Header Detected");
831                 ret = 1;
832         }
833
834 exit:
835         if (pFileIO == NULL && fp != NULL)
836                 mmfile_close(fp);
837
838         return ret;
839 }
840
841
842 /***********************************************************************/
843 /*                     REAL Header Check API                            */
844 /***********************************************************************/
845
846 int MMFileFormatIsValidREAL(MMFileIOHandle *pFileIO, const char *mmfileuri, int dummy)
847 {
848 #define _MMFILE_RMVB_HEADER_LENGTH 4    /*RMF*/
849
850         MMFileIOHandle *fp = pFileIO;
851         unsigned char buffer[_MMFILE_RMVB_HEADER_LENGTH] = {0, };
852         int ret = 0;
853
854         if (fp == NULL)
855                 mm_file_retvm_if_fails(DEBUG, mmfile_open(&fp, mmfileuri, MMFILE_RDONLY) == MMFILE_UTIL_SUCCESS, MMFILE_UTIL_FAIL);
856
857         mmfile_seek(fp, 0L, MMFILE_SEEK_SET);
858
859         if (mmfile_read(fp, buffer, _MMFILE_RMVB_HEADER_LENGTH) != _MMFILE_RMVB_HEADER_LENGTH) {
860                 debug_error(RELEASE, "read error");
861                 goto exit;
862         }
863
864         if (!memcmp(buffer, ".RMF", 4)) {
865                 debug_msg(RELEASE, "Header Detected");
866                 ret = 1;
867         }
868
869 exit:
870         if (pFileIO == NULL && fp != NULL)
871                 mmfile_close(fp);
872
873         return ret;
874 }
875
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
883
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
888
889
890 int MMFileFormatIsValidMPEGTS(MMFileIOHandle *pFileIO, const char *mmfileuri, int dummy)
891 {
892         MMFileIOHandle *fp = pFileIO;
893         unsigned char buffer[TS_MAX_PACKET_SIZE] = {0, };
894         int ret = 0;
895
896         if (fp == NULL)
897                 mm_file_retvm_if_fails(DEBUG, mmfile_open(&fp, mmfileuri, MMFILE_RDONLY) == MMFILE_UTIL_SUCCESS, MMFILE_UTIL_FAIL);
898
899         mmfile_seek(fp, 0L, MMFILE_SEEK_SET);
900
901         if (mmfile_read(fp, buffer, TS_MAX_PACKET_SIZE) != TS_MAX_PACKET_SIZE) {
902                 debug_error(RELEASE, "read error");
903                 goto exit;
904         }
905
906         if (_MMFileIsMPEGTSHeader(fp) != MPEGTS_NONE) {
907                 debug_msg(RELEASE, "Header Detected");
908                 ret = 1;
909         }
910
911 exit:
912         if (pFileIO == NULL && fp != NULL)
913                 mmfile_close(fp);
914
915         return ret;
916 }
917
918 /***********************************************************************/
919 /*                     MPEG-PS Header Check API                            */
920 /***********************************************************************/
921
922 int MMFileFormatIsValidMPEGPS(MMFileIOHandle *pFileIO, const char *mmfileuri, int dummy)
923 {
924 #define _MMFILE_MPEGPS_HEADER_LENGTH 4
925
926         MMFileIOHandle *fp = pFileIO;
927         unsigned char buffer[_MMFILE_MPEGPS_HEADER_LENGTH] = {0, };
928         int ret = 0;
929
930         if (fp == NULL)
931                 mm_file_retvm_if_fails(DEBUG, mmfile_open(&fp, mmfileuri, MMFILE_RDONLY) == MMFILE_UTIL_SUCCESS, MMFILE_UTIL_FAIL);
932
933         mmfile_seek(fp, 0L, MMFILE_SEEK_SET);
934
935         if (mmfile_read(fp, buffer, _MMFILE_MPEGPS_HEADER_LENGTH) != _MMFILE_MPEGPS_HEADER_LENGTH) {
936                 debug_error(RELEASE, "read error");
937                 goto exit;
938         }
939
940         if ((buffer[0] == 0x00) && (buffer[1] == 0x00) && (buffer[2] == 0x01) && (buffer[3] == 0xba)) {
941                 debug_msg(RELEASE, "Header Detected");
942                 ret = 1;
943         }
944
945 exit:
946         if (pFileIO == NULL && fp != NULL)
947                 mmfile_close(fp);
948
949         return ret;
950 }
951
952 /***********************************************************************/
953 /*                     MPEG AUDIO Header Check API                            */
954 /***********************************************************************/
955
956 int MMFileFormatIsValidMPEGAUDIO(MMFileIOHandle *pFileIO, const char *mmfileuri, int dummy)
957 {
958 #define _MMFILE_MPEGAUDIO_HEADER_LENGTH 4
959
960         MMFileIOHandle *fp = pFileIO;
961         unsigned char buffer[_MMFILE_MPEGAUDIO_HEADER_LENGTH] = {0, };
962         int ret = 0;
963
964         if (fp == NULL)
965                 mm_file_retvm_if_fails(DEBUG, mmfile_open(&fp, mmfileuri, MMFILE_RDONLY) == MMFILE_UTIL_SUCCESS, MMFILE_UTIL_FAIL);
966
967         mmfile_seek(fp, 0L, MMFILE_SEEK_SET);
968
969         if (mmfile_read(fp, buffer, _MMFILE_MPEGAUDIO_HEADER_LENGTH) != _MMFILE_MPEGAUDIO_HEADER_LENGTH) {
970                 debug_error(RELEASE, "read error");
971                 goto exit;
972         }
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");
977                 ret = 1;
978         }
979
980 exit:
981         if (pFileIO == NULL && fp != NULL)
982                 mmfile_close(fp);
983
984         return ret;
985 }
986
987 /***********************************************************************/
988 /*                     MPEG VIDEO Header Check API                            */
989 /***********************************************************************/
990
991 int MMFileFormatIsValidMPEGVIDEO(MMFileIOHandle *pFileIO, const char *mmfileuri, int dummy)
992 {
993 #define _MMFILE_MPEGVIDEO_HEADER_LENGTH 4
994
995         MMFileIOHandle *fp = pFileIO;
996         unsigned char buffer[_MMFILE_MPEGVIDEO_HEADER_LENGTH] = {0, };
997         int ret = 0;
998
999         if (fp == NULL)
1000                 mm_file_retvm_if_fails(DEBUG, mmfile_open(&fp, mmfileuri, MMFILE_RDONLY) == MMFILE_UTIL_SUCCESS, MMFILE_UTIL_FAIL);
1001
1002         mmfile_seek(fp, 0L, MMFILE_SEEK_SET);
1003
1004         if (mmfile_read(fp, buffer, _MMFILE_MPEGVIDEO_HEADER_LENGTH) != _MMFILE_MPEGVIDEO_HEADER_LENGTH) {
1005                 debug_error(RELEASE, "read error");
1006                 goto exit;
1007         }
1008
1009         if ((buffer[0] == 0x00) && (buffer[1] == 0x00) && (buffer[2] == 0x01) && (buffer[3] == 0xb3)) {
1010                 debug_msg(RELEASE, "Header Detected");
1011                 ret = 1;
1012         }
1013
1014 exit:
1015         if (pFileIO == NULL && fp != NULL)
1016                 mmfile_close(fp);
1017
1018         return ret;
1019 }
1020
1021 /***********************************************************************/
1022 /*                     AIFF Header Check API                                  */
1023 /***********************************************************************/
1024
1025 int MMFileFormatIsValidAIFF(MMFileIOHandle *pFileIO, const char *mmfileuri, int dummy)
1026 {
1027 #define _MMFILE_AIFF_HEADER_LENGTH 13
1028
1029         MMFileIOHandle *fp = pFileIO;
1030         unsigned char buffer[_MMFILE_AIFF_HEADER_LENGTH] = {0, };
1031         int ret = 0;
1032
1033         if (fp == NULL)
1034                 mm_file_retvm_if_fails(DEBUG, mmfile_open(&fp, mmfileuri, MMFILE_RDONLY) == MMFILE_UTIL_SUCCESS, MMFILE_UTIL_FAIL);
1035
1036         mmfile_seek(fp, 0L, MMFILE_SEEK_SET);
1037
1038         if (mmfile_read(fp, buffer, _MMFILE_AIFF_HEADER_LENGTH) != _MMFILE_AIFF_HEADER_LENGTH) {
1039                 debug_error(RELEASE, "read error");
1040                 goto exit;
1041         }
1042
1043         if (!memcmp(buffer, "FORM", 4) && !memcmp(buffer + 8, "AIFF", 4)) {
1044                 debug_msg(RELEASE, "Header Detected");
1045                 ret = 1;
1046         }
1047
1048 exit:
1049         if (pFileIO == NULL && fp != NULL)
1050                 mmfile_close(fp);
1051
1052         return ret;
1053 }
1054
1055
1056 int MMFileFormatIsValidAPE(MMFileIOHandle *pFileIO, const char *mmfileuri, int dummy)
1057 {
1058 #define _MMFILE_APE_HEADER_LENGTH 4     /*APE*/
1059
1060         MMFileIOHandle *fp = pFileIO;
1061         unsigned char buffer[_MMFILE_APE_HEADER_LENGTH] = {0, };
1062         int ret = 0;
1063
1064         if (fp == NULL)
1065                 mm_file_retvm_if_fails(DEBUG, mmfile_open(&fp, mmfileuri, MMFILE_RDONLY) == MMFILE_UTIL_SUCCESS, MMFILE_UTIL_FAIL);
1066
1067         mmfile_seek(fp, 0L, MMFILE_SEEK_SET);
1068
1069         if (mmfile_read(fp, buffer, _MMFILE_APE_HEADER_LENGTH) != _MMFILE_APE_HEADER_LENGTH) {
1070                 debug_error(RELEASE, "read error");
1071                 goto exit;
1072         }
1073
1074         if (!memcmp(buffer, "MAC ", 4)) {
1075                 debug_msg(RELEASE, "Header Detected");
1076                 ret = 1;
1077         }
1078
1079 exit:
1080         if (pFileIO == NULL && fp != NULL)
1081                 mmfile_close(fp);
1082
1083         return ret;
1084 }
1085
1086 /***********************************************************************/
1087 /*            Implementation of Internal Functions                     */
1088 /***********************************************************************/
1089 static bool _MMFileIsMMFHeader(void *header)
1090 {
1091 #define _MMFILE_MMF_TYPE_POSITION       0x11
1092         unsigned char *s = header;
1093
1094         mm_file_retv_if_fails(memcmp(s, "MMMD", 4) == 0, false);
1095
1096         /* warning: comparison is always true due to limited range of data type */
1097         if (s[_MMFILE_MMF_TYPE_POSITION] <= 0x2F)
1098                 return true;
1099
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))) {
1104
1105                 return true;
1106         }
1107
1108         return false;
1109 }
1110
1111 static int _MMFileIsMPEGTSHeader(MMFileIOHandle *fp)
1112 {
1113         unsigned char buffer[TS_MAX_PACKET_SIZE] = {0, };
1114         unsigned char *s = NULL;
1115         unsigned long startoffset = 0;
1116
1117         mmfile_seek(fp, 0, MMFILE_SEEK_SET);
1118         mmfile_read(fp, buffer, TS_MAX_PACKET_SIZE);
1119
1120         s = (unsigned char *)memchr(buffer, 0x47, TS_MAX_PACKET_SIZE);
1121         mm_file_retv_if_fails(s, MPEGTS_NONE);
1122
1123         startoffset = s - buffer + 1;
1124
1125         memset(&buffer, 0x00, TS_MAX_PACKET_SIZE);
1126
1127         mmfile_seek(fp, startoffset, MMFILE_SEEK_SET);
1128         mmfile_read(fp, buffer, TS_MAX_PACKET_SIZE);
1129
1130         if (buffer[TS_PACKET_SIZE - 1] & 0x47)
1131                 return MPEGTS_PACKET;
1132         else if (buffer[TS_DVHS_PACKET_SIZE - 1] & 0x47)
1133                 return MPEGTS_DVHS;
1134         else if (buffer[TS_FEC_PACKET_SIZE - 1] & 0x47)
1135                 return MPEGTS_FECE;
1136
1137         return MPEGTS_NONE;
1138 }
1139
1140 static int _MMFileIsMP3Header(void *header)
1141 {
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,}
1150                 },
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,}
1154                 },
1155         };
1156
1157         static const unsigned int mp3types_freqs[3][3] = {
1158                 {11025, 12000, 8000},
1159                 {22050, 24000, 16000},
1160                 {44100, 48000, 32000}
1161         };
1162
1163         static const unsigned int mp3FrameCoef[4][4] = {
1164                 { -1, 48, 144, 72},
1165                 { -1, -1, -1, -1},
1166                 { -1, 48, 144, 72},
1167                 { -1, 48, 144, 144}
1168         };
1169
1170         /* header */
1171         head = MMFILE_CONVERT_INT(headc);
1172         mm_file_retv_if_fails((head & 0xffe00000) == 0xffe00000, 0);
1173
1174         /* we don't need extension, copyright, original or
1175         * emphasis for the frame length */
1176         head >>= 6;
1177
1178         /* mode */
1179         /*mode = head & 0x3;*/
1180         head >>= 3;
1181
1182         /* padding */
1183         length = head & 0x1;
1184         head >>= 1;
1185
1186         /* sampling frequency */
1187         samplerate = head & 0x3;
1188         mm_file_retv_if_fails(samplerate != 3, 0);
1189
1190         head >>= 2;
1191
1192         /* bitrate index */
1193         bitrate = head & 0xF;
1194         mm_file_retv_if_fails(bitrate != 15, 0);
1195
1196         /* ignore error correction, too */
1197         head >>= 5;
1198
1199         /* layer */
1200         layer = 4 - (head & 0x3);
1201         mm_file_retv_if_fails(layer != 4, 0);
1202
1203         head >>= 2;
1204
1205         /* version 0=MPEG2.5; 2=MPEG2; 3=MPEG1 */
1206         version = head & 0x3;
1207         mm_file_retv_if_fails(version != 1, 0);
1208
1209         /* lookup */
1210         /*channels = (mode == 3) ? 1 : 2;*/
1211         samplerate = mp3types_freqs[version > 0 ? version - 1 : 0][samplerate];
1212         {
1213                 /* calculating */
1214                 bitrate = mp3types_bitrates[version == 3 ? 0 : 1][layer - 1][bitrate];
1215                 coef = mp3FrameCoef[version][layer];
1216                 if (layer == 1)
1217                         length = length * 4;
1218
1219                 length = length + ((coef * bitrate * 1000) / samplerate);
1220         }
1221
1222         return length;
1223 }
1224
1225 static bool _MMFileSearchID3Tag(MMFileIOHandle *fp, unsigned int *offset)
1226 {
1227 #define _MMFILE_MP3_TAGV2_HEADER_LEN 10
1228
1229         unsigned char tagHeader[_MMFILE_MP3_TAGV2_HEADER_LEN] = {0, };
1230         unsigned int tagInfoSize = 0;
1231         unsigned int acc_tagsize = 0;
1232         int tagVersion = 0;
1233         int encSize = 0;
1234         bool ret = 0;
1235
1236         /*init offset*/
1237         *offset = 0;
1238
1239         mmfile_seek(fp, 0, MMFILE_SEEK_SET);
1240
1241 _START_TAG_SEARCH:
1242
1243         if (mmfile_read(fp, tagHeader, _MMFILE_MP3_TAGV2_HEADER_LEN) != _MMFILE_MP3_TAGV2_HEADER_LEN) {
1244                 debug_error(RELEASE, "read error occured.");
1245                 return false;
1246         }
1247
1248         if (memcmp(tagHeader, "ID3", 3) == 0) {
1249                 debug_msg(RELEASE, "'ID3' found.");
1250         } else {
1251                 debug_msg(RELEASE, "'ID3' not found.");
1252                 return ret;
1253         }
1254
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.");
1260         } else {
1261                 debug_warning(DEBUG, "It's bad ID3V2 tag.");
1262                 return ret;
1263         }
1264
1265         tagVersion = tagHeader[3];
1266
1267         mm_file_retvm_if_fails(RELEASE, tagVersion <= 4, ret);
1268
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));
1272
1273         acc_tagsize += tagInfoSize;
1274         debug_msg(RELEASE, "tag size: %u, offset: %u", tagInfoSize, acc_tagsize);
1275
1276         mmfile_seek(fp, acc_tagsize, MMFILE_SEEK_SET);
1277         *offset = acc_tagsize;
1278
1279         ret = true;
1280
1281         /** Some contents has many ID3 tag. Use last one */
1282         goto _START_TAG_SEARCH;
1283 }